有点困惑。 fmap
听起来可以map
遍历Maybe
的整个列表,但是如果我使用例如fApplyFunctor = (+1) <$> [Just 1, Just 2]
。
看起来非常正常的是:map ((+1) <$>) [Just 1, Just 2, Just 3]
。从某种意义上说,这似乎是过大的,我记得fmap
本身已经可以做到这一点...
答案 0 :(得分:9)
没有fmap
意味着您可以映射到任意Functor
类型上(现在将其作为一个集合来考虑),但是您只能这样做 “ functor level” 深。如果您用列表fmap
,则它完全等效于map
。
fmap
是在各种Functor
上定义的,例如列表,Maybe
等。在这里,您可以在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]
编辑:就像@DanielWagner所说的那样,存在一种数据类型Compose
,该数据类型可以处理两个(如果是级联,则为更多){ 1}} s,因此使我们可以Functor
深入两个级别。实现方式如下:
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
中,因此还需要一些额外的工作。