fmap和Haskell的“平面地图”

所有这一次,当Haskell演讲中谈到“平面地图”时,通常就Monad而言,我认为它被称为“平坦”是有原因的,即它将容器弄平。 所以

[[1,2],[3,4]]

将被处理,就像它一样

[1,2,3,4]

但是现在我发现fmap和map基本上是一样的,唯一的区别是一个用于函子,另一个用于列表。 最后,这只是为了避免在使用地图时混淆错误消息。

真的吗? 如果是的话为什么fmap中的f来表示“平坦”,为什么不是“函数图”?


如果是这样,为什么fmap f来表示“平坦”,为什么不是“函数图”?

你的直觉是对的: fmap f 确实代表“函数图”,而不是“平面图”。 事实上,在较新的相似语言中,例如PureScript,其名称就是map 。 虽然Haskell map首先被定义为列表,但想出一个新名字很困难。 使用Functor的F是一个简单的,如果不是特别有创意的选择。

讲师更可能指的是一元绑定函数>>= 。 由于x >>= fjoin (fmap fx)的等价性,bind在其他语言中有时也被称为flatMap 。 它具有您期望的列表行为,例如:

> [1,2,3] >>= x -> [x,x]
[1,1,2,2,3,3]

尽管如此,请记住这一点很重要,即这个“平面图”不会递归地变成任意深度。 事实上,编写这样一个函数在Haskell中是不可能的,没有一些复杂的类型特技。 自己尝试: flatten函数的类型签名会是什么样子,即使是直接在列表上运行的类型签名也是如此?

flatten :: ??? -> [a]

>>=函数的比较非常简单:它与fmap类似,但每个输出元素都必须包含在函子中,而>>=将结果浅显地“扁平化”成单个包装。 这个操作是monad的本质,这就是为什么>>=函数存在于Monad类型类中,但fmapFunctor

这个答案取自一些关于原始问题的评论,所以我已经标记为社区维基。 欢迎编辑和改进。


下面是一些如何在Haskell中做flatMap明确的等价例子。

Prelude> map (replicate 3) [1..4]
[[1,1,1],[2,2,2],[3,3,3],[4,4,4]]
Prelude> fmap (replicate 3) [1..4]
[[1,1,1],[2,2,2],[3,3,3],[4,4,4]]
Prelude> concat [[1,2],[3,4]]
[1,2,3,4]
Prelude> concat (map (replicate 3) [1..4])
[1,1,1,2,2,2,3,3,3,4,4,4]
Prelude> concat $ map (replicate 3) [1..4]
[1,1,1,2,2,2,3,3,3,4,4,4]
Prelude> concatMap (replicate 3) [1..4]
[1,1,1,2,2,2,3,3,3,4,4,4]
Prelude> replicate 3 `concatMap` [1..4]
[1,1,1,2,2,2,3,3,3,4,4,4]
Prelude> [1..4] >>= replicate 3
[1,1,1,2,2,2,3,3,3,4,4,4]

应该清楚的是, flatMap首先映射然后是平坦的,然后将地图的输出变平,而不是扁平化您要处理的输入列表(这不是flatMap ,它没有名称,它只是一个平面然后映射)。

链接地址: http://www.djcxy.com/p/43337.html

上一篇: fmap and "flat map" in Haskell

下一篇: Haskell: class system extension proposal