【问题标题】:Where does the word "flatMap" originate from?“flatMap”这个词是从哪里来的?
【发布时间】:2018-09-25 08:44:04
【问题描述】:

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

我所知道的最古老的外观是在 Scala 中。 在 Haskell 中,它被称为 bind。 在范畴论中使用希腊符号。

【问题讨论】:

  • 列表版本在 Haskell 中称为concatMap,因为它是concat . map。在 Scala(以及其他)中,concat 被称为 flatten,所以 flatMap 有意义。
  • @sepp2k 感谢您的回复。我明白这个词的意思。我对这里的历史概览感兴趣。
  • 如果您将flatMap 替换为map,您将得到一个列表列表。如果你flatten 得到结果,你会得到来自flatMap 的结果。 map 存在于 60 年代的 Lisp 和一个变体中,maplist 在 58 的原始 lisp 论文中。在 CL 中,flatMap 被称为 mapcanCLHS 解释它与 (apply #'nconc (mapcar f x1 ... xn)) 相同。因此,在名称中使用flattenconcat 仅表明用户将列表视为数据或参数。
  • @Sylwester 在不相关的切线上,我曾经尝试过(mapcon #'(lambda (x) x) (list 1 2 3))。你能不试就知道它的作用吗? /只是为了好玩/
  • @WillNess 在第一次迭代之后你有(1 2 3),第二次之后它是(1 . #1=(2 3 . #1#)),它会停留一段时间,同时它试图到达最后一对以应用下一个:-p Btw我想我说mapcanflatMap 有点快,因为flatMap 本质上可能没有破坏性。

标签: functional-programming language-agnostic monads terminology history


【解决方案1】:

部分答案,希望能提供一些有用的“种子节点”来开始更彻底的搜索。我的最佳猜测:

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

函数/方法名称flatMap 似乎是由flatten 和ma​​p 组成的组合词。这是有道理的,因为每当M 是一些monad、AB 一些类型,而a: M[A]f: A => M[B] 是一个值和一个函数,那么mapflatMap 和@ 的实现987654340@应该满足

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

(在 Scala 语法中)。

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

地图

map-函数似乎从远古时代就被用来映射列表。我最好的猜测是它来自 Lisp(大约 1958 年),然后传播到所有其他具有类似高阶函数的语言。

展平

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

flatten 在 monad 的上下文中的使用肯定是最近才出现的,因为 monad 本身在编程中引入的时间很晚。如果我们在单子计算的上下文中寻找“flatten”这个词的用法,我们可能至少应该查看 Eugenio Moggi 的论文。事实上,在 1988 年的 "Computational Lambda-Calculus and Monads" 中,他使用了以下公式:

备注 2.2:直观地说,eta_A: A -> TA 将值包含到计算中,而 mu_A: T^2 A -> TA 扁平化 计算的计算 到计算中。

(排版由我更改,强调我的,斜体文本与原文相同)。我认为 Moggi 谈到扁平化计算,而不仅仅是列表,这很有趣。

数学符号/“希腊语”

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

平面地图

要找到flatMap portmanteau 这个词的起源,我建议从今天最突出的普及者开始,然后尝试从那里回溯。显然,flatMap is a Scala meme,所以从 Scala 开始似乎是合理的。人们可能会检查通常怀疑的标准库(尤其是List 数据结构):影响 Scala 的语言。这些“根”在 Odersky 的“Scala 编程”的第 1 章第 1.4 节中命名:

  • C、C++ 和 C# 可能不是它的来源。
  • 在 Java 中情况正好相反:flatMap 来自 Scala 到 Java 1.8 版。
  • Smalltalk 我无话可说
  • Ruby 肯定是 has flat_map on Enumerable,但我对 Ruby 一无所知,也不想深入研究源代码以了解它是何时引入的。
  • Algol 和 Simula:绝对不是。
  • 奇怪的是ML(SML)seems to get by without flatMap,它只有concat(与flatten基本相同)。 OCaml 的列表还有 seem to have flatten, but no flatMap
  • 正如您已经提到的,Haskell 很久以前就有这一切,但在 Haskell 中它被称为 bind 并写成运算符
  • Erlanghas flatmap on lists,但不知道是不是这个起源,还是后来介绍的。 Erlang 的问题在于它是从 1986 年开始的,那时还没有 github。
  • 关于 Iswim、Beta 和 gbeta,我无话可说。

我认为可以说flatMap 已被 Scala 普及,原因有两个:

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

总结一下:“扁平化”术语从一开始就被用于 monad 的上下文中。后来,它与map结合成flatMap,并被Scala推广,或者更具体地说是Apache Spark和Scalaz等框架。

【讨论】:

  • 正在阅读... SML 有List.concat : 'a list list -> 'a list
  • 感谢@D.BenKnoble,已修复。
【解决方案2】:

flatmap 在“计算机程序的结构和解释”的第 2.2.3 节序列作为常规接口中被介绍为

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

这本书的第一版出版于 1985 年。

【讨论】:

  • 就像noted 在书中一样,“David Turner 向 [SICP 的作者] 展示了这种嵌套映射的方法,他的语言 KRC 和 Miranda 提供了处理这些结构的优雅形式。示例本节中的内容(另见练习 2.42)改编自 Turner 1981。” 那个是1981年的KRCpaper
  • (contd.) 谈到使用“ZF 表达式”(即列表推导式)使用嵌套生成器解决回溯问题——这意味着concatMapping。跨度>
猜你喜欢
  • 1970-01-01
  • 2020-07-31
  • 2019-11-18
  • 2014-10-23
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多