Where does the word “flatMap” originate from?
如今,flatMap是用于对类monad对象进行对应操作的最广泛使用的名称。
但是我找不到它第一次出现在哪里以及什么使它流行。
我知道的最古老的外观是在Scala中。
在Haskell中,它称为bind。
在类别理论中,使用希腊表示法。
- 列表版本在Haskell中称为concatMap,因为它是concat . map。在Scala中(其中包括)concat被称为flatten,因此flatMap是有意义的。
-
@ sepp2k感谢您的回复。我了解这个词的意思。我对这里的历史概述感兴趣。
-
如果将flatMap替换为map,则会返回列表列表。如果flatten结果,则从flatMap获得结果。 map在60年代的Lisp中存在,并且是58版本的原始Lisp纸中的maplist变体。在CL flatMap中被称为mapcan,CLHS解释说它与(apply #'nconc (mapcar f x1 ... xn))相同。因此,名称中使用flatten或concat仅表示用户将列表视为数据或参数的观点。
-
@Sylwester在不相关的切线上,我曾经尝试过(mapcon #'(lambda (x) x) (list 1 2 3))。您能不做尝试就说出它的作用吗? /纯娱乐/
-
@WillNess在第一次迭代之后,您有了(1 2 3),而在第二次迭代之后,它是(1 . #1=(2 3 . #1#)),它停留了一段时间,同时试图到达最后一对以应用下一个:-p Btw我想我说的有点快mapcan是flatMap,因为flatMap可能不是破坏性的。
-
@Sylwester是的。 IOW一个非常讨厌的惊喜。 :)
部分答案,希望可以提供一些有用的"种子节点"以开始更彻底的搜索。我最好的猜测:
-
1958 for map用于列表处理,
-
1988年用于单子上下文的flatten,
-
flatMap 2004作为Scala中支持for -comprehensions的重要方法。
函数/方法名称flatMap似乎是由flatten和map组成的portmanteau词。这是有道理的,因为无论何时M是某种单子,A,B是某种类型,并且a: M[A],f: A => M[B]是一个值和一个函数,则map,flatMap和flatten应该满足
1
| a.flatMap(f) = a.map(f).flatten |
(使用Scala语法)。
首先让我们分别考虑两个组件map和flatten。
地图
自远古以来,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谈论扁平化计算,而不仅仅是列表,这很有趣。
数学符号/"希腊语"
在数学表示法中使用的希腊语:在范畴论中,引入单子词的更常见方法是通过对应于pure和flatten的自然变换,不再强调对应于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之类的框架推广。
- 只是阅读... SML具有List.concat : 'a list list -> 'a list
-
感谢@ D.BenKnoble,已修复。
flatMap在《计算机程序的结构和解释》的2.2.3节中作为常规接口引入为
1 2
| (define (flatmap proc seq)
(accumulate append nil (map proc seq))) |
该书的第一版于1985年出版。
-
正如书中所提到的,"嵌套映射的方法已由David Turner展示给[SICP作者],他的语言KRC和Miranda为处理这些构造提供了优雅的形式主义。本节中的示例(另请参见练习2.42)改编自1981年KRC的特纳(Turner 1981)。
-
(续)讨论了使用带有嵌套生成器的" ZF表达式"(即列表推导)解决回溯问题的方法-这意味着concatMap ping。