gmapM
似乎是基于Data.Data
编写通用遍历的明显候选者,例如,如果想要实现MonoTraversable
。唯一的打嗝是需要Monad
而不是Applicative
。这是为什么?此外,假设较弱的fmapM
是否有类似的功能?
答案 0 :(得分:3)
它看起来像是在实施Monad-Applicative提案之前的历史细节。
我可以根据gmapM
定义Applicative
默认值和列表实例。
gmapM :: forall m a. (Data a, Applicative m) => (forall d. Data d => d -> m d) -> a -> m a
gmapM f = gfoldl k pure
where
k :: Data d => m (d -> b) -> d -> m b
k c x = c <*> f x
-- instance Data a => Data [a] where ...
gmapMlist :: forall m a. (Data a, Applicative m) => (forall d. Data d => d -> m d) -> [a] -> m [a]
gmapMlist _ [] = pure []
gmapMlist f (x:xs) = (:) <$> f x <*> f xs