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

05-11 11:26