关于函数式编程:” flatMap”一词从何而来?

Where does the word “flatMap” originate from?

如今,flatMap是用于对类monad对象进行对应操作的最广泛使用的名称。
但是我找不到它第一次出现在哪里以及什么使它流行。

我知道的最古老的外观是在Scala中。
在Haskell中,它称为bind
在类别理论中,使用希腊表示法。


部分答案,希望可以提供一些有用的"种子节点"以开始更彻底的搜索。我最好的猜测:

  • 1958 for map用于列表处理,
  • 1988年用于单子上下文的flatten
  • flatMap 2004作为Scala中支持for -comprehensions的重要方法。

函数/方法名称flatMap似乎是由flatten和map组成的portmanteau词。这是有道理的,因为无论何时M是某种单子,AB是某种类型,并且a: M[A]f: A => M[B]是一个值和一个函数,则mapflatMapflatten应该满足

1
a.flatMap(f) = a.map(f).flatten

(使用Scala语法)。

首先让我们分别考虑两个组件mapflatten

地图

自远古以来,map功能似乎已用于映射列表。我最好的猜测是它来自Lisp(大约在1958年),然后传播到所有其他具有类似高阶函数的语言。

扁平

鉴于Lisp中的列表代表了多少东西,我假设flatten也已用于列表处理。

在monads中使用flatten必须是最近的,因为monads本身已经在以后的编程中引入了。如果我们在单子计算的上下文中寻找"变平"一词的用法,我们可能至少应该检查Eugenio Moggi的论文。实际上,在1988年的"计算Lambda微积分和Monads"中,他使用的公式是:

Remark 2.2: Intuitively eta_A: A -> TA gives the inclusion of values into computations, while mu_A: T^2 A -> TA flatten a computation of a computation into a computation.

(我改变了字体,重点是我的字体,原文是斜体)。我认为Moggi谈论扁平化计算,而不仅仅是列表,这很有趣。

数学符号/"希腊语"

在数学表示法中使用的希腊语:在范畴论中,引入单子词的更常见方法是通过对应于pureflatten的自然变换,不再强调对应于flatMap的词素。但是,没有人称其为"扁平化"。例如,Maclane将与方法pure对应的自然变换称为"单位"(不要与方法unit混淆),并且与Monoids类似,通常将flatten称为"乘法"。人们可能会进一步调查当"三重"术语更为普遍时是否有所不同。

flatMap

要找到flatMap portmanteau单词的起源,我建议先从当今最著名的大众化词开始,然后尝试从那里回溯。显然,flatMap是一个Scala模因,因此从Scala开始似乎是合理的。一个人可能会检查通常怀疑的标准库(尤其是List数据结构):影响Scala的语言。这些"根"在Odersky的"在Scala中编程"的第1章第1.4节中被命名:

  • C,C和C#可能不是它的来源。
  • 在Java中则是相反的情况:flatMap从Scala进入Java的1.8版。
  • 关于Smalltalk我无话可说
  • Ruby在Enumerable上肯定有flat_map,但是我对Ruby一无所知,也不想深入研究源代码以了解何时引入。
  • Algol和Simula:绝对不是。
  • 奇怪的是,没有flatMap的机器学习(SML)似乎足够了,它只有concat(本质上与flatten相同)。 OCaml的列表似乎也有flatten,但没有flatMap
  • 正如您已经提到的,Haskell在很久以前就拥有所有这些,但是在Haskell中,它称为bind并以操作符的形式编写
  • Erlang在列表上有,但是我不确定这是起源还是以后引入的。 Erlang的问题在于它是从1986年开始的,那时还没有github。
  • 关于Iswim,Beta和gbeta我什么也不能说。

我认为可以公平地说flatMap已由Scala推广,原因有二:

  • flatMap在Scala的集合库的设计中扮演了重要角色,几年后,它被证明可以很好地推广到大型分布式集合(Apache Spark和类似工具)
  • flatMap成为每个决定在JVM上正确进行函数式编程的人的最爱(Scalaz和受Scalaz启发的库,例如Scala Cats)

总结一下:从一开始就在monads的上下文中使用了"扁平化"术语。后来,它与map组合为flatMap,并由Scala或更具体地由诸如Apache Spark和Scalaz之类的框架推广。


flatMap在《计算机程序的结构和解释》的2.2.3节中作为常规接口引入为

1
2
(define (flatmap proc seq)
  (accumulate append nil (map proc seq)))

该书的第一版于1985年出版。