函数式编程中的扩展技术,如F#

Car*_*ngo 10 f# functional-programming

在面向对象编程中,继承和虚拟方法是创建可扩展代码的常见方案.在更复杂的设置中,工厂方法(或依赖框架)有助于扩展基本代码.

函数式编程(例如F#)中创建可扩展代码的常用方法是什么?

Jon*_*rop 10

太棒了!

以下是从这篇博客文章中得出的答案:

功能范例(意味着使用高阶函数)仅提供单一形式的可扩展性:高阶函数.这些允许您分解"内部"功能.例如,经常出现相同的第一个和最后一个代码块的代码:

let f x =
  first x
  stuff1 x
  last x

let g x =
  first x
  stuff2 x
  last x
Run Code Online (Sandbox Code Playgroud)

可以考虑从特定情况重用的一般高阶函数:

let hof stuff x =
  first x
  stuff x
  last x

let f = hof stuff1 x

let g = hof stuff2 x
Run Code Online (Sandbox Code Playgroud)

积极地应用它会导致设计模式,例如解析器组合器,并且是一种非常强大且轻量级的技术,可以使代码可扩展.但是,它不会使数据类型可扩展.

但实际的函数式编程语言几乎总是包含更有趣的语言功能来帮助实现可扩展性:

  • Common Lisp具有Common Lisp对象系统(CLOS)和宏系统.
  • 标准ML具有参数多态性和高阶模块系统.
  • OCaml添加了多态变体,对象,可选参数和Camlp4宏系统.
  • Haskell具有参数多态和类型类,而Template Haskell添加了宏.
  • Scala具有Java风格的OOP,并具有一些附加功能.

阅读Chris Okasaki的优秀专着Purely功能数据结构,用于使用标准ML中的高阶模块和Haskell中的类型类的一些很好的例子.通过Jacques Garrigue的多态变体阅读代码重用,以了解该语言特性如何用于攻击表达式问题.然而,这些解决方案在野外非常罕见,特别是没有它们你可以走很长的路(例如在F#中).

从历史上看,这种多样性的出现是因为大多数函数式编程语言都是研究项目,因此,它们的存在增加了新的特性.因此,我们现在在当今的函数式编程语言中有各种各样的不同形式的可扩展性.

F#是一种不同的野兽,因为它的设计要求是与.NET的其余部分(强加.NET风格的OOP)和实用主义的无缝互操作性.因此,F#保持ML核心具有参数多态性并添加.NET的对象系统.因此,您可以从通用高阶函数和传统OOP提供的简单可扩展性中受益,但不能从任何更深奥的功能(如高阶模块,类型类和宏)中获益.

F#开创性的唯一可扩展性形式是活跃模式.这些允许您将通过模式匹配进行结构化的代码与具体数据表示分开.这是将代码与数据分离的重要方法,因此使其更具可重用性.

  • @Stephen:我满足于F#的可扩展性,因为它足以成为一个非常有用的工具,是的.我确实想念多态变体.事实上,我一直在编写解析器,并且必须编写,消除歧义并维护`type assoc = Left | 非| 与OCaml相比,F#或Haskell中的正确联合类型对我来说感觉很乏味.Okasaki让我也错过了高阶模块.然而,关于F#的重要之处在于,您可以更轻松地使用它解决许多实际问题,而不是它将所有功能都置于阳光下.:-) (2认同)

Tom*_*cek 5

函数式编程中的基本扩展技术是

  • 编写高阶函数(将其他函数作为参数的函数)
  • (函数)多态性(使用由类型参数化的函数和类型 - 在 C# 术语中,泛型类型和方法)。

例如,您可能会传递一个函数作为参数,而不是使用抽象方法(修改对象的某些状态)。该函数将采用所有必要的状态来进行计算(通过面向对象中的抽象方法完成),并将返回新状态(或任何计算结果)。

通用(多态)代码list<T>是扩展技术的另一个例子。您有一些使用它的数据结构和函数(例如List.map),您可以将它与以前未知的类型(列表项的类型)一起使用,并指定特定于此类型的行为(例如过滤谓词)。列表是非常基本的示例,但它也适用于非集合类型。

在更复杂的设置中,编程语言之间存在更大的差异

  • 在 Haskell 中,人们可能使用类型类(这有点像更强大的接口)
  • 在 OCaml 中,人们使用函子(类似于经典的函数多态性,但您也可以通过多个函数和类型进行参数化)。
  • 我认为,在 F# 中,人们通常将标准 .NET 技术(例如接口)与基本函数技术(高阶函数、将函数作为参数传递给对象构造函数等)混合在一起。

FP 和 OO 的这种组合是一个非常强大的组合,因此您可能不需要像依赖框架这样更复杂的东西。