sequence :: Monad m => [m a] -> m [a]
获取计算列表并将它们组合成一个计算,该计算收集其结果列表。序列具有
Monad
约束也是历史事故,因为它实际上只能以Applicative
的形式实现。
事实上,sequenceA
对Applicative
类型进行操作。
sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)
但是请等一下,为什么sequenceA
在没有它的情况下可以实现Traversable
约束?
seqA :: Applicative f => [f a] -> f [a]
seqA = foldr fx (pure [])
where
fx f fs = pure (:) <*> f <*> fs)
答案 0 :(得分:7)
这是一个可能最初令人困惑的主题,因为它周围有很多历史和变化,而旧的解释已经过时了。历史大致如下:
sequence
操作的想法可以追溯到20世纪90年代,当时Monad
类被纳入Haskell,人们首先为它制定了通用操作。您从Typeclassopedia引用的签名反映了这一点:sequence :: Monad m => [m a] -> m [a]
。它可以与任何monad一起使用,但它在列表上工作是硬编码的。 Applicative
班是在2000年代中后期开发的;每个人都引用的开创性论文是McBride和Patterson(2008),"Applicative Programming with Effects"。麦克布莱德和帕特森也注意到:
sequence
操作实际上可以推广到dist :: Applicative f => [f a] -> f [a]
。 Monad
约束太窄了!mapM
功能(与sequence
关闭)概括为traverse :: Applicative f => (a -> f b) -> [a] -> f [b]
。Traversable
类来推广到非列表数据结构。Applicative
和Traversable
类添加到GHC base
库中,并进行了一些小的更改。 dist
函数的名称为sequenceA
,而Foldable
类的加入Traversable
仅适用于仅支持Traversable
要求子集的类型。sequence :: Monad m => [m a] -> m [a]
签名在后见之明错误。 Applicative
成为Monad
的超类)和Foldable/Traversable Proposal时,基础库是修改后,以使他们接近理想,后见之明的设计。 然而,可折叠/可交叉提案未改变sequence
的签名。我不能确切地告诉你为什么,但答案将是一些钝化的细节,归结为历史原因,向后兼容性或类似的东西。但我可以告诉你,如果我们可以重新开始:
sequence
会有sequenceA
的签名; sequenceA
不会独立于sequence
; mapM
只是traverse
,签名错误,因此也不会独立存在。