在阅读类型类时,我已经看到Functors,Applicative Functors和Monads之间的关系是严格增加的权力.函数是可以映射的类型.Applicative Functors可以使用某些效果执行相同的操作.Monads与可能不受限制的效果相同.此外:
Every Monad is an Applicative Functor
Every Applicative Functor is a Functor
Run Code Online (Sandbox Code Playgroud)
Applicative Functor的定义清楚地表明了这一点:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
但Monad的定义是:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
m >> n = m >>= \_ -> n
fail :: String -> m a
Run Code Online (Sandbox Code Playgroud)
根据Brent Yorgey的伟大类词库,monad的另一种定义可能是:
class Applicative m => Monad' m where
(>>=) :: m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
这显然更简单,并将巩固Functor <Applicative Functor <Monad.那么为什么这不是定义呢?我知道applicative functor是新的,但根据2010年Haskell Report第80页,这没有改变.为什么是这样?
ehi*_*ird 27
每个人都希望看到Applicative成为Monad的超类,但它会破坏如此多的代码(如果return被淘汰,每个当前的Monad实例都变得无效),每个人都想要推迟,直到我们能够以这样的方式扩展语言,避免破坏代码(请参阅此处了解一个重要提案).
Haskell 2010总体上是一种保守的渐进式改进,仅标准化了一些无争议的扩展,并在一个领域打破了兼容性,使标准与每个现有实现一致.事实上,哈斯克尔2010的图书馆甚至不包括应用型-少了些什么人都来自期望标准库比你想象的是标准化的.
希望我们很快就会看到情况有所改善,但幸运的是,这通常只是一个轻微的不便(必须写liftM代替fmap通用代码等).
此时更改Monad的定义会破坏许多现有代码(定义Monad实例的任何代码段)是值得的.
如果对变化有很大的实际好处,那么打破这种向后兼容性是值得的.在这种情况下,利益并不是那么大(而且主要是理论上的)并且不能证明这一数量的破损.