Typeclassopedia呈现Traversable:
class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) sequenceA :: Applicative f => t (f a) -> f (t a) mapM :: Monad m => (a -> m b) -> t a -> m (t b) sequence :: Monad m => t (m a) -> m (t a)
一个很好的练习是弄清楚默认实现应该是什么:给定traverse或sequenceA,你将如何定义其他三个方法?
我想出了以下代码检查代码:
class (Functor t, Foldable t) => MyTraversable t where traverse' :: Applicative f => (a -> f b) -> t a -> f (t b) traverse' = error "..." sequenceA' :: Applicative f => t (f a) -> f (t a) sequenceA' f = traverse' id f mapM :: Monad m => (a -> m b) -> t a -> m (t b) mapM = traverse' sequence' :: Monad m => t (m a) -> m (t a) sequence' = sequenceA'
如果我的实现mapM
和sequence'
正确,并且,因为每个Monad都是一个适用者:
?: :i Monad class Applicative m => Monad (m :: * -> *) where ...
那么它是我不明白为什么mapM
和sequence'
甚至是必要的.他们为什么?
PS - 信用和我感谢haoformayor帮助我sequenceA
.
正如评论中提到的,有一段时间不是每个人Monad
都是Applicative
.就在最近(base-4.8
与GHC 7.10一起发布),Applicative
它成为了一个超类Monad
.你可能已经看过Applicative-Monad-Proposal,AMP.
目前的不归路单子,MRP(电子邮件线程)的合作上,这将使
Monad
的>>
和Applicative
的*>
相同.哪个事件很可能会说明traverse = mapM
和sequence = sequenceA
.但这是一个漫长的过程,需要时间.
所以回答你的问题:出于历史原因.