MonadApplicative 的子类型。

Monad 的 Haskell 定义

class Applicative m => Monad m where
return :: a -> m a
return = pure
 
(>>=)  :: m a -> (a -> m b) -> m b
 
(>>)   :: m a -> m b -> m b
m >> n = m >>= \_ -> n
 
join :: m (m a) -> m a
join = (>>= id)

Monad 在 GHC 8.8 之后才被实现为 Applicative 的子类型,区别在于之前的实现中 Monad 还包含一个 fail 的函数。

在实现中,函数 returnApplicative 的函数 pure 的定义应该是相同 的,可以理解为早期 Monad 没有被实现为 Applicative 子类时取了一个错误的名字。同样的原因,函数 (>>) 和 Applicative 的函数 (*>) 相同,并且虽然 (>>) 有默认的实现,但在实现中一般不符合语义,默认实现中直接保留了 m b,也就是第二个参数的盒子和内容,而正确的语义应该是保留 m a 的盒子和 m b 的结果,也就是将第二个参数盒子中的内容取出放入第一个参数的盒子当中,和 Applicative 的 (*>)语义相同。

(>>=) 函数叫做 bind ,将第一个参数中的值取出,绑定到第二个参数的计算中去。

Monad 应当满足的条件

return a >>= k = k a
m >>= return   = m
m >>= (\x -> k x >>= h) = (m >>= k) >>= h