这是一个最初可能令人困惑的主题,因为它周围有很多历史和变化,而旧的解释已经过时了.历史大致是这样的:
该sequence
操作的概念可以追溯到20世纪90年代,当时该Monad
课程被纳入Haskell,人们首先为它制定了通用操作.您从Typeclassopedia引用的签名反映了这一点:sequence :: Monad m => [m a] -> m [a]
.它可以与任何monad一起使用,但它在列表上工作是硬编码的.
该Applicative
课程是在2000年代中后期开发的; 每个人都引用的开创性论文是McBride和Patterson(2008),"有效的应用程序设计".麦克布莱德和帕特森也注意到:
sequence
事实上,旧的monadic 操作可以推广到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]
签名在后见之明是错误的.
因此,最后,快进到2015年,当GHC实现的应用型/ Monad的建议(请Applicative
的超类Monad
)和可折叠/ Traversable的议案,那里的基础库中,以便让他们接近理想,事后知情的修改设计.
然而,可折叠/可交易的提案没有改变签名sequence
.我不能确切地告诉你为什么,但答案将是一些钝化的细节,归结为历史原因,向后兼容性或类似的东西.但我可以告诉你,如果我们可以重新开始:
sequence
会有sequenceA
签名;
sequenceA
不会独立存在sequence
;
mapM
只是traverse
带有错误的签名,因此也不会独立存在.