- short names inside modules. I.e. you might have a function called Foo.merge(...) instead of x.merge_with_foo(...)
- a way to bring modules into scope so you don’t need to specify the name
- not using that many modules. Most lines of code won’t have more than one or two function calls so it shouldn’t matter that much (other techniques can be used in complicated situations)
The key advantage of type-dependant name resolution is in using the same names for different types. You might want to write code like foo.map(...) and it is ok if you don’t know the exact type of foo. With modules you may need to know whether to call SimpleFoo.map or CompoundFoo.map.
If anything, this is an aid to type-checking. Since MyModule.foo takes only things of type t, the type-checker's job is extremely easy and it will help you a lot more in cases when your program is incomplete.
So often when using C#-style fluent APIs I find that I'm completely on my own and have to turn a half-written line into something syntactically correct before Intellisense gives me anything useful. Using an F#-style MyModule.foo, the compiler can tell me everything.