Here are some notes about the technical distinctions.
Modules can be 'open'ed (unless they have RequireQualifiedAccessAttribute). That is, if you put functions (F
and G
) in a module (M
), then you can write
open M
... F x ... G x ...
whereas with a static method, you'd always write
... M.F x ... M.G x ...
Module functions cannot be overloaded. Functions in a module are let-bound, and let-bound functions do not permit overloading. If you want to be able to call both
X.F(someInt)
X.F(someInt, someString)
you must use member
s of a type, which only work with 'qualified' calls (e.g. type.StaticMember(...)
or object.InstanceMember(...)
).
(Are there other differences? I can't recall.)
Those are the main technical differences that influence the choice of one over the other.
Additionally, there is some tendency in the F# runtime (FSharp.Core.dll) to use modules only for F#-specific types (that are typically not used when doing interop with other .Net languages) and static methods for APIs that are more language-neutral. For example, all the functions with curried parameters appear in modules (curried functions are non-trivial to call from other languages).