【问题标题】:F# coding style - static vs instance methodsF# 编码风格 - 静态与实例方法
【发布时间】:2012-08-01 19:20:49
【问题描述】:

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

mySet.Add(elem);

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

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

我经常在示例中看到后一种形式。在我看来,两者在语义和功能上都完全相同,但来自 C# 背景,使用实例方法感觉更自然。 F# 中哪种风格更好,为什么?

【问题讨论】:

  • 有很多原因,根植于整个函数式编程,有些是 F# 特有的,很难知道从哪里开始证明它的合理性。一旦你熟悉了函数式编程,它就会变得显而易见。
  • 它只涉及 2 种样式,oo 和 fp。由于 f# 是多范式,我想两者兼而有之是有意义的。

标签: c# coding-style f#


【解决方案1】:

除了该答案中提到的与类型推断相关的原因之外,在函数式样式中更自然地将函数作为参数发送。 如果它是一个实例方法,你将不得不写这样的东西:

myHigherOrderFunction (fun (x:MyType) -> x.myFunctionAsMethod)

但如果它被定义为静态方法你可以写:

myHigherOrderFunction MyType.myFunctionAsMethod

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

实例方法需要类型的实例才能访问函数(方法),在 OOP 中这不是问题,因为您认为在向对象发送消息时,但在 FP 中,单独的函数(没有实例)是第一个阶级公民。

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

【讨论】:

  • fp 风格的优秀用例。而且在编程oo风格中,实例函数更短。
【解决方案2】:

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

mySet.Add(elem);

看起来mySet 被突变为包含elem,此时 F# 集将返回一个新的mySet。幸运的是,F# 无法编译以确保您不会犯此错误,它仍然会导致代码混乱。相比之下:

mySet |> Set.Add elm

形式不同,看起来会返回一些新的东西,而不会与原来的相差太远。

【讨论】:

    【解决方案3】:

    虽然 F# 中的静态方法很常见,但我发现实例方法对组件开发很有意义。

    原因? F# 模块系统缺少函子。在其他类型的 ML(例如 SML 或 OCaml)中,您将组件开发为简单的模块。如果您稍后决定参数化模块,则可以将其提升为仿函数,而无需重写太多源代码。在 F# 中你不能。

    要在 F# 中创建参数化“模块”,您必须借助类并将方法转换为实例方法,并在实例构造期间传入参数。不幸的是,从一个模块到一个类涉及相当多的机械但烦人的源代码更改。因此,核心组件程序员可能会选择默认使用类和实例方法,就像在 C# 中一样。这让人想起有时在 SML 中使用的“仅函子”风格。

    【讨论】:

      【解决方案4】:

      在 f# 中,作为函数式语言,它更原生地分离不可变的变量和作为操作的函数。这个函数类似于 c# 中的静态方法,但是函数比 c# 方法有一个优点。是部分应用。您可以将一些(不是全部)参数传递给函数,这个带有部分参数的函数将是需要其他参数的新函数。

      【讨论】:

        猜你喜欢
        • 2012-11-12
        • 1970-01-01
        • 2015-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-30
        • 1970-01-01
        相关资源
        最近更新 更多