monad本意是单子。在haskell中,第一个接触的基本都是IO action,通过把IO动作包装起来我们能很方便的与现实世界进行数据交换。但其实monad的用途不止如此,monad还能讲一系列操作进行序列化,而这一点在通常编程中是非常需要的。而在haskell中,类似的事情则是通过递归来完成了平时需要序列化的工作。但其实haskell中也有能进行顺序操作的方法,那就是monad。一个类似于monad的定义基本是这个样子的。
class Computation c where
success :: a -> c a
failure :: String -> c a
augment :: c a -> (a -> c b) -> c b
combine :: c a -> c a -> c a
第一个success即是讲一个动作包裹成computation类型,代表一次顺利的操作,第二个failure代表一个失败的操作,取一个字符串返回一个c包裹的a,第三个augment取两个参数,一个是之前的操作,另一个是一个能将a变成c包裹的b的函数,并返回一个c包裹的b。这其实就是将操作序列化。第四个combine就是去两个之前获得的c包裹的a并产生一个新的同类型
一个完整定义的monad差不多是这个
class Monad m where
return :: a -> m a
fail :: String -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
第一个success即return,failure即fail, augment即>>=,combine即>>,不同的是,>>中的定义更宽泛点,是>>=的简化版本,省略掉了中间的a
对于monad一共有三个转义定律
do {e} → e
讲一个操作用do单独包裹起来等于他自己
do {e;es} → e>>do {es}
讲一个序列操作包裹起来等于e执行完以后将结果交给do {es}串起来
do {let decls; es} → let decls in do {es}
在do中有let可以将它提取出来
monad还必须符合三个定义
return a >>= f ≡ f a
将一个a return并赋值给f继续计算恒等于直接对a进行f计算
f >>= return ≡ f
将一个f计算的结果给return返回恒等于直接进行f计算
f >>= (\x -> g x >>= h) ≡ (f >>= g) >>= h
monad中符合结合律,及f的计算结果给(\x->g x >>=h)恒等于(f>>=g)的结果给h