At any level of scope other than module scope, it is not an error to reuse a value or function name
In your example below, you’re opening the thing module before calling foo :
module thing =
let foo x y = x + y
open thing
let foo = foo 5
foo 10
That is most probably the compiler hiding thing.foo from us, but still keeping track of the fact that foo is defined under module thing, and that’s different than a foo defined in whatever module you’re opening thing from. So you’re not redefining foo within the same module here.
Oh, the other thing re shadowing is, if you open multiple modules and they have the same definitions, the one from the module opened later shadows the one from the module opened earlier. So that’s something to watch for as style guide warns us about.
“A top-level module declaration includes the whole file in the module.”
And later:
“If a code file does not begin with a top-level module declaration or a namespace declaration, the whole contents of the file, including any local modules, becomes part of an implicitly created top-level module that has the same name as the file, without the extension, with the first letter converted to uppercase.”
So, because the code in my first example was not in an explicitly-named module - it was just in a script - it was actually in an implicitly-named module and therefore:
“At any level of scope other than module scope, it is not an error to reuse a value or function name.”
…applies when coupled with:
“However, at the top level scope in a module, names must be unique.”
…because it is actually at “module scope” even though that’s not explicit, but the code is at the top level so the names have to be unique.
I think I now understand this a little bit better than I have explained my understanding of it above.