解释工人的组合器

Mat*_*ick 91 functional-programming combinators

什么是组合器?

它是"没有自由变量的函数或定义"(在SO上定义)?

或者如何:根据John Hughes在他着名的关于Arrows的论文中,"组合器是一个从程序片段构建程序片段的函数",这是有利的,因为"......使用组合器的程序员构建了大部分所需的自动编程,而不是手工编写每个细节".他接着说,mapfilter是这样的组合子的两个常见的例子.

一些符合第一个定义的组合器:

一些符合第二个定义的组合器:

  • 地图
  • 过滤
  • 折叠/减少(推测)
  • 任何>> =,撰写,fmap ?????

我对第一个定义不感兴趣 - 那些不能帮我写一个真正的程序(如果你说服我错了,那就是+1). 请帮我理解第二个定义.我认为map,filter和reduce非常有用:它们允许我在更高级别编程 - 更少的错误,更短更清晰的代码.以下是关于组合器的一些具体问题:

  1. 有哪些组合器的例子,例如map,filter?
  2. 编程语言经常实现哪些组合器?
  3. 组合器如何帮助我设计更好的API?
  4. 如何设计有效的组合器?
  5. 什么是类似于非功能语言(比如Java)的组合器,或者这些语言用什么来代替组合器?

更新

感谢@CA McCann,我现在对组合器有了更好的理解.但有一个问题对我来说仍然是一个棘手的问题:

用大量使用组合器写的函数程序和没有写的函数程序有什么区别?

我怀疑答案是组合器重型版本更短,更清晰,更通用,但如果可能的话,我希望进行更深入的讨论.

我也在寻找更多关于复杂组合器的例子和解释(比复杂的组合fold语言).

C. *_*ann 92

我对第一个定义不感兴趣 - 那些不能帮我写一个真正的程序(如果你说服我错了,那就是+1).请帮我理解第二个定义.我认为map,filter和reduce非常有用:它们允许我在更高级别编程 - 更少的错误,更短更清晰的代码.

这两个定义基本相同.第一个是基于形式定义,您给出的示例是原始组合器 - 可能的最小构建块.他们可以帮助您编写真正的程序,只要与它们一起构建更复杂的组合器.可以把S和K这样的组合作为假设的"组合计算机"的机器语言.当然,实际的计算机不能以这种方式工作,所以在实践中你通常会以其他方式在幕后实现更高级别的操作,但概念基础仍然是理解那些更高层次意义的有用工具.操作.

你给出的第二个定义是非正式的,关于使用更复杂的组合器,以高阶函数的形式,以各种方式组合其他函数.请注意,如果基本构建块是上面的原始组合器,那么从它们构建的所有内容都是高阶函数和组合器.然而,在存在其他基元的语言中,您可以区分是或不是函数的东西,在这种情况下,组合器通常被定义为以一般方式操纵其他函数的函数,而不是在任何非函数上操作功能直接.

有哪些组合器的例子,例如map,filter?

列出太多了!这两者都将描述单个值上的行为的函数转换为描述整个集合上的行为的函数.您还可以使用转换其他函数的函数,例如端到端组合它们,或者拆分和重新组合参数.您可以使用组合器将单步操作转换为生成或使用集合的递归操作.或者其他各种各样的东西,真的.

编程语言经常实现哪些组合器?

这会有很大差异.相对较少的完全通用的组合器 - 大多数是上面提到的原始组合器 - 因此在大多数情况下,组合器将对所使用的任何数据结构有一定的认识(即使这些数据结构是由其他组合器构建的),其中通常情况下,通常会有一些"完全通用"的组合器,然后是某些人决定提供的各种专用形式.有一些荒谬的案例(适当的广义版本)地图,折叠和展开足以完成您可能想要的几乎所有事情.

组合器如何帮助我设计更好的API?

正如您所说的那样,通过思考高级操作以及这些交互的方式,而不是低级细节.

想想"for each"式循环在集合中的流行度,它可以让你抽象出枚举集合的细节.在大多数情况下,这些只是映射/折叠操作,通过使它成为组合器(而不是内置语法),您可以执行诸如获取两个现有循环并以多种方式直接组合它们之类的东西 - 将一个嵌套在另一个内部,一个接一个地做,依此类推 - 只需应用一个组合器,而不是整理一大堆代码.

如何设计有效的组合器?

首先,考虑一下哪些操作对程序使用的任何数据都有意义.然后考虑如何以通用方式有意义地组合这些操作,以及如何将操作分解为连接在一起的较小部分.主要的是使用转换操作,而不是直接操作.如果你的函数只是以不透明的方式执行一些复杂的功能,并且只吐出某种预先消化的结果,那么你就无法做到这一点.将最终结果保留给使用组合器的代码- 您需要从A点到B点的事物,而不是期望成为过程开始或结束的事物.

什么是类似于非功能语言(比如Java)的组合器,或者这些语言用什么来代替组合器?

Ahahahaha.有趣的是你应该问,因为对象首先是高阶的东西 - 它们有一些数据,但它们也带有一堆操作,并且很多构成良好OOP设计的内容归结为"对象应该通常像组合器,而不是数据结构".

因此,这里最好的答案可能是,它们使用的是具有大量getter和setter方法或公共字段的类,而不是类似组合器的东西,而逻辑主要包括执行一些不透明的预定义操作.