F#代码组织:类型和模块

Bru*_*eis 18 f# module code-organization static-members

如何在模块内部编写函数或作为某种类型的静态成员之间做出决定?

例如,在F#的源代码中,有许多类型与同名模块一起定义,如下所示:

type MyType = // ...

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module MyType = // ...
Run Code Online (Sandbox Code Playgroud)

为什么不简单地将操作定义为MyType类型的静态成员?

Bri*_*ian 26

以下是关于技术差异的一些注释.

模块可以"开放"(除非它们具有RequireQualifiedAccessAttribute).也就是说,如果将函数(FG)放在模块(M)中,那么就可以编写了

open M
... F x ... G x ...
Run Code Online (Sandbox Code Playgroud)

而使用静态方法,你总是写

... M.F x ... M.G x ...
Run Code Online (Sandbox Code Playgroud)

模块功能不能超载.模块中的函数是let-bound,而let-bound函数不允许重载.如果你想能够同时打电话

X.F(someInt)
X.F(someInt, someString)
Run Code Online (Sandbox Code Playgroud)

你必须使用member一种类型的s,它只适用于'合格'的调用(例如type.StaticMember(...)object.InstanceMember(...)).

(还有其他差异吗?我不记得了.)

这些是影响一个选择的主要技术差异.

此外,F#运行时(FSharp.Core.dll)中存在一些趋势,即仅将模块用于F#特定类型(通常在与其他.Net语言进行互操作时不使用)和更多语言的API的静态方法-中性.例如,带有curried参数的所有函数都出现在模块中(curried函数对于从其他语言调用来说是非常重要的).