有点混乱。fmap
听起来可以在Maybe
的列表中使用map
,但如果我使用例如fApplyFunctor = (+1) <$> [Just 1, Just 2]
,则无法使其工作。
看起来非常好用的是:map ((+1) <$>) [Just 1, Just 2, Just 3]
。这似乎有些过头了,因为我记得fmap
已经可以自己做到了。。。
没有fmap
意味着您可以在任意Functor
类型上映射(我们现在将其视为一个集合(,但您只能在一个"函子级别">深度上执行此操作。如果您使用列表fmap
,则它与map
完全等效。
然而,fmap
是在所有类型的Functor
s上定义的,如列表、Maybe
s等。因此,在这里,fmap
中的fmap
可以映射到两个级别:
fApplyFunctor =fmap (fmap (+1))[Just 1, Just 2]
这将导致:
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]
EDIT:正如@DanielWagner所说,存在一种数据类型Compose
,它可以在两个(如果您级联,则可以工作两个以上(Functor
s上工作,因此允许我们深入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)
所以这里我们再次在两个级别上执行fmap
:
Prelude Data.Functor.Compose> getCompose ((+1) <$> Compose [Just 1, Just 2])
[Just 2,Just 3]
但正如您所看到的,它需要一些语法来首先将数据包装在Compose
中,然后再将其从Compose
中"展开",因此这也需要一些额外的工作。