Как Вы решаете между записью функции в модуле или как статический член некоторого типа?
Например, в исходном коде F#, существует много типов, которые определяются наряду с одинаково именованным модулем, следующим образом:
type MyType = // ...
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module MyType = // ...
Почему Вы просто не определяете операции как статических членов типа MyType?
Вот несколько примечаний о технических различиях.
Модули можно «открыть» (если они не имеют RequireQualifiedAccessAttribute). То есть, если вы поместите функции ( F
и G
) в модуль ( M
), тогда вы можете написать
open M
... F x ... G x ...
, тогда как с помощью статического метода, вы всегда должны писать
... M.F x ... M.G x ...
Функции модуля не могут быть перегружены . Функции в модуле привязаны к let, а функции с привязкой let не допускают перегрузки. Если вы хотите иметь возможность вызывать оба
X.F(someInt)
X.F(someInt, someString)
, вы должны использовать члены
типа, которые работают только с «квалифицированными» вызовами (например, type.StaticMember (...)
] или объект.InstanceMember (...)
).
(Есть ли другие отличия? Я не могу вспомнить.)
Это основные технические различия, которые влияют на выбор одного по сравнению с другим.
Кроме того, в среде выполнения F # (FSharp.Core.dll) наблюдается некоторая тенденция к использованию модулей только для специфичных для F # типов (которые обычно не используются при взаимодействии с другими языками .Net) и статических методов для API, которые более нейтральны к языку.Например, все функции с каррированными параметрами появляются в модулях (каррированные функции нетривиально вызывать из других языков).
В F# я предпочитаю статический член на типе, а не функцию в модуле, если ...