所有这一次,当任何Haskell演讲中谈到"平面地图"时,通常与Monads有关,我认为它被称为"平面",原因是它平坦了容器.所以
[[1,2],[3,4]]
Run Code Online (Sandbox Code Playgroud)
将被处理就像它一样
[1,2,3,4]
Run Code Online (Sandbox Code Playgroud)
但是现在我发现fmap和map基本上是一回事,唯一的区别是一个用于仿函数而另一个用于just列表.最后,这只是在使用map时避免混淆错误消息.
真的吗?如果是这样,为什么f在fmap中意味着"平坦",为什么不"functor map"?
Ale*_*ing 30
如果是的话,为什么
f在fmap来意味"扁平化",为什么不"仿函数图"?
你的直觉是正确的:f在fmap 不主张"函子图",而不是"平面地图"在所有.实际上,在较新的类似语言中,例如PureScript,名称就是这样map.然而,Haskell map首先是为列表定义的,因此提出一个新名称很困难.使用Functor中的F是一个简单的(如果不是特别有创意的话)选择.
讲师更有可能是指monadic bind函数,>>=.由于x >>= f等价join (fmap f x),有时也会flatMap在其他语言中调用bind .它具有您在列表中所期望的行为,例如:
> [1,2,3] >>= \x -> [x,x]
[1,1,2,2,3,3]
Run Code Online (Sandbox Code Playgroud)
但是,请记住,这个"平面地图"不会递归地变平到任意深度,这一点很重要.实际上,如果没有复杂的类型类技巧,在Haskell中编写这样的函数实际上是不可能的.自己尝试一下:flatten函数的类型签名是什么样的,即使是直接在列表上运行的签名?
flatten :: ??? -> [a]
Run Code Online (Sandbox Code Playgroud)
>>=相比之下,该函数非常简单:它就像是fmap,但每个输出元素必须包含在仿函数中,并将>>=结果浅"扁平化"为单个包装器.这个操作是monad的本质,这就是为什么>>=函数存在于Monad类型类中,但是fmap在Functor.
这个答案来自原始问题的一些评论,因此我将其标记为社区维基.欢迎编辑和改进.
div*_*ero 10
以下是一些明确的等效示例,说明如何flatMap在 Haskell 中执行操作。
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]
Run Code Online (Sandbox Code Playgroud)
应该清楚的flatMap是,先映射然后扁平化,你扁平化地图的输出,而不是扁平化你将要处理的输入列表(这不是flatMap,这没有名字,它只是一个扁平化然后地图)。
| 归档时间: |
|
| 查看次数: |
8139 次 |
| 最近记录: |