Monad 是 Applicative 的子类型。
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
的函数。
在实现中,函数 return
和 Applicative 的函数 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