在Haskell中的列表上映射Functor

Mad*_*ote 7 haskell functor map-function

有点困惑.fmap听起来它可以在map所有的列表中Maybe,但如果我使用eg,我无法让它工作fApplyFunctor = (+1) <$> [Just 1, Just 2].

看起来完美无缺的是:map ((+1) <$>) [Just 1, Just 2, Just 3].从某种意义上来说,这似乎有点矫枉过正,我记得fmap已经可以做到这一点......

Wil*_*sem 9

没有fmap意味着你可以映射任意Functor类型(现在好好把它想象成一个集合),但你只能做一个"仿函数级别".如果你fmap有一个列表,它完全等同于map.

fmap但是在各种Functors上定义,比如列表,Maybes等.这里你可以fmap两个层面上fmap进行映射:

fApplyFunctor = fmap (fmap (+1)) [Just 1, Just 2]
Run Code Online (Sandbox Code Playgroud)

这将导致:

Prelude> fmap (fmap (+1)) [Just 1, Just 2]
[Just 2,Just 3]
Prelude> (fmap (+1)) <$> [Just 1, Just 2]
[Just 2,Just 3]
Prelude> ((+1) <$>) <$> [Just 1, Just 2]
[Just 2,Just 3]
Run Code Online (Sandbox Code Playgroud)

编辑:像@DanielWagner所说,存在一种数据类型Compose,它可以在两个(或更多,如果你级联)Functors上工作,从而允许我们fmap深入两个层次.这实现如下:

newtype Compose f g a = Compose { getCompose :: f (g a) }

instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose x) = Compose (fmap (fmap f) x)
Run Code Online (Sandbox Code Playgroud)

所以在这里我们再次执行fmap两个级别:

Prelude Data.Functor.Compose> getCompose ((+1) <$> Compose [Just 1, Just 2])
[Just 2,Just 3]
Run Code Online (Sandbox Code Playgroud)

但正如你所看到的那样,它需要一些语法来首先将数据包装在a中Compose,然后再将其"解包"出来Compose,所以这需要一些额外的工作.

  • 还有`(+ 1)<$> Compose [Just 1,Just 2]`.但是在我遇到的每一个真实案例中,引入"Compose"比在两次输入`fmap`时语法更重,所以...来自我的答案+1.=) (6认同)