F#编程风格 - 静态方法 vs 实例方法

7

我注意到在F#中静态方法比C#更受欢迎。在C#中,你总是通过调用实例方法来向集合中添加元素:

mySet.Add(elem);

但在 F# 中通常有一个等价的静态方法:

mySet.Add(elem)
// OR
Set.Add elem mySet

我经常在示例代码中看到这两种形式。在语义和功能上,它们对我来说完全相同,但作为一名C#程序员,使用实例方法会更自然。在F#中哪种风格更好?为什么呢?


相关内容:https://dev59.com/T2sz5IYBdhLWcg3wuKa6 - Daniel
有很多理由支持函数式编程作为一种整体,还有一些是特别适用于F#的,这些理由太多了,很难知道从哪里开始来证明它的价值。一旦你熟悉了函数式编程,它就会变得显而易见。 - Daniel
它只涉及两种风格,oo和fp。由于F#是多范式的,我想同时使用两种风格是有意义的。 - nicolas
4个回答

8
除了与类型推断相关的原因之外,在函数式风格中,将函数作为参数发送更加自然。 如果它是一个实例方法,您将不得不编写像这样的代码:
myHigherOrderFunction (fun (x:MyType) -> x.myFunctionAsMethod)

但如果它被定义为静态方法,你可以这样编写代码:

myHigherOrderFunction MyType.myFunctionAsMethod

哪种方式更加优雅,更容易编写(也更容易阅读),并且几乎与发送常规let绑定函数时的语法相同。

实例方法需要类型的实例才能访问函数(方法),在面向对象编程中,这不是问题,因为您会考虑向对象发送消息,但在函数式编程中,仅有函数(没有实例)也是一等公民。

要访问静态方法,您需要指定类,可以将类视为带有函数的容器(如模块或命名空间)。


函数式编程风格的使用案例非常优秀。在面向对象编程中,实例函数比较短。 - nicolas

5

大多数标准F#类型都是不可变的。在使用不可变对象时,静态方法可以更好地描述正在发生的事情,例如:

mySet.Add(elem);

看起来mySet被改变以包含elem,而F#集合会返回一个新的mySet。幸运的是,F#编译失败,以确保您不会犯这个错误,但仍然会导致混乱的代码。相比之下:

mySet |> Set.Add elm

这个东西在形式上很独特,看起来将会返回一些新的内容,而不会离原始内容太远。


2

虽然在F#中静态方法非常常见,但我发现对于组件开发来说,实例方法更有意义。

原因是,F#模块系统缺少functor。在其他ML风格(如SML或OCaml)中,您将组件开发为简单的模块。如果您稍后决定参数化该模块,则可以将其升级为functor而无需重写太多源代码。在F#中您不能这样做。

要在F#中创建参数化的“模块”,必须使用类并将方法转换为实例方法,在实例构造期间传递参数。不幸的是,从模块转换为类涉及相当多的机械但繁琐的源代码更改。因此,一位专业的组件程序员可能会选择默认使用类和实例方法,就像在C#中一样。这类似于有时在SML中采用的“仅限functor”样式。


0
在函数式编程语言F#中,更本地化的方式是将不可变的变量和操作作为函数分离。这类似于C#中的静态方法,但函数有一个优势,那就是部分应用。您可以向函数传递一些(而不是全部)参数,这个带有部分参数的函数将成为需要其他参数的新函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接