我注意到静态方法在 F# 中似乎比 C# 更受欢迎。在 C# 中,您总是通过调用实例方法将元素添加到集合中:
mySet.Add(elem);
但在 F# 中通常有一个等效的静态方法:
mySet.Add(elem)
// OR
Set.Add elem mySet
我经常在样本中看到后一种形式。在我看来,两者在语义和功能上都完全相同,但来自 C# 背景,使用实例方法感觉更自然。F# 中哪种风格更好,为什么?
我注意到静态方法在 F# 中似乎比 C# 更受欢迎。在 C# 中,您总是通过调用实例方法将元素添加到集合中:
mySet.Add(elem);
但在 F# 中通常有一个等效的静态方法:
mySet.Add(elem)
// OR
Set.Add elem mySet
我经常在样本中看到后一种形式。在我看来,两者在语义和功能上都完全相同,但来自 C# 背景,使用实例方法感觉更自然。F# 中哪种风格更好,为什么?
除了该答案中提到的与类型推断相关的原因之外,在功能样式中,将函数作为参数发送更自然。如果它是实例方法,则必须编写如下内容:
myHigherOrderFunction (fun (x:MyType) -> x.myFunctionAsMethod)
但如果它被定义为静态方法,您可以编写:
myHigherOrderFunction MyType.myFunctionAsMethod
它更优雅,更易于编写(也易于阅读),并且与发送常规 let 绑定函数时的语法几乎相同。
实例方法需要类型的实例才能访问函数(方法),在 OOP 中这不是问题,因为您认为在向对象发送消息时,但在 FP 中,函数本身(没有实例)是一等公民。
要访问静态方法,您需要指定 Class,您可以将 Class 视为一种具有函数的容器(如模块或命名空间)。
大多数标准 F# 类型都是不可变的。在使用不可变对象时,静态方法可以更好地描述正在发生的事情,例如:
mySet.Add(elem);
当F# 集返回一个新mySet
的. 幸运的是,F# 无法编译以确保您不会犯此错误,它仍然会导致代码混乱。相比之下:elem
mySet
mySet |> Set.Add elm
形式独特,看起来会返回一些新的东西,而不会与原来的距离太远。
虽然 F# 中的静态方法很常见,但我发现实例方法对于组件开发很有意义。
原因?F# 模块系统缺少函子。在其他类型的 ML(例如 SML 或 OCaml)中,您将组件开发为简单的模块。如果您稍后决定参数化模块,则可以将其提升为仿函数,而无需重写太多源代码。在 F# 中你不能。
要在 F# 中创建参数化“模块”,您必须借助类并将方法转换为实例方法,并在实例构造期间传入参数。不幸的是,从一个模块到一个类涉及相当多的机械但烦人的源代码更改。因此,核心组件程序员可能会选择默认使用类和实例方法,就像在 C# 中一样。这让人想起有时在 SML 中使用的“仅函子”风格。
在 f# 中,作为函数式语言,它更原生地分离不可变的变量和作为操作的函数。这个函数类似于 c# 中的静态方法,但是函数比 c# 方法有一个优点。是部分应用。您可以将一些(不是全部)参数传递给函数,这个带有部分参数的函数将是需要其他参数的新函数。