Вот некоторые заметки о технических различиях.
Модули могут быть «открыты» (если у них нет RequireQualifiedAccessAttribute). То есть, если вы помещаете функции (F
и G
) в модуль (M
), то вы можете написать
open M
... F x ... G x ...
тогда как при статическом методе вы всегда пишете
... M.F x ... M.G x ...
Функции модуля не могут быть перегружены . Функции в модуле имеют функцию let-bound, а функции let-bound не допускают перегрузки. Если вы хотите иметь возможность позвонить как
X.F(someInt)
X.F(someInt, someString)
вы должны использовать member
s типа, которые работают только с «квалифицированными» вызовами (например, type.StaticMember(...)
или object.InstanceMember(...)
).
(Есть ли другие различия? Я не могу вспомнить.)
Это основные технические различия, которые влияют на выбор одного над другим.
Кроме того, во время выполнения F # (FSharp.Core.dll) существует некоторая тенденция использовать модули только для F # -специфических типов (которые обычно не используются при взаимодействии с другими языками .Net) и статические методы для API, которые более не зависит от языка. Например, все функции с параметрами карри появляются в модулях (функции карри не тривиальны для вызова из других языков).