monad 是支持>>=
操作的 applicative 函子,>>=
读作绑定,它的类型是:
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
即取一个 monad 和一个函数,返回一个新的 monad。monad 有专属的类型类——Monad,其定义如下:
class Applicative m => Monad (m :: * -> *) where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
return
和 applicative 的pure
一样,都是取一个值,把它放在能产生这个值的最小默认上下文中。>>=
前面说过了,>>
有一个默认实现,就是把一个 monad 直接换成另一个 monad 返回,fail
不会被主动调用,在一些特定语法结构中,会被 Haskell 用于模式匹配。
一个类型要成为 monad 不仅要满足 Monad 类型类的条件,还要满足 monad 定律(虽然编译器并不会帮你检查):
- 左单位元:return x >>= f 和 f x 等价
- 右单位元:m >>= return 和 m 等价
- 结合律:(m >>= f) >>= g 和 m >>= (\x -> f x >>= g) 等价