Haskell语言学习笔记(6)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
Monad(单子)是个类型类,它至少包含一个return函数以及一个bind(>>=)操作符。

Monad的法则

Left identity:	return a >>= f ≡ f a
Right identity:	m >>= return ≡ m
Associativity:	(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

[] 是 Monad

instance Monad []  where
    return x = [x]
    xs >>= f = [y | x <- xs, y <- f x]
    xs >> ys  = [y | _ <- xs, y <- ys]
    fail _ = []
Prelude> [3,4,5] >>= \x -> [x,-x]
[3,-3,4,-4,5,-5]
Prelude> do { x <- [3,4,5]; [x,-x] }
[3,-3,4,-4,5,-5]
证明[]符合Monad法则:
1. return a >>= f ≡ f a
return a >>= f ≡ [a] >>= f ≡ [y | x <- [a], y <- f x] ≡ [y | y <- f a] ≡ f a 
2. m >>= return ≡ m
m >>= return ≡ [y | x <- m, y <- return x] ≡ [y | x <- m, y <- [x]] ≡ [x | x <- m] ≡ m
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
(m >>= f) >>= g
≡ [y | x <- m, y <- f x] >>= g
≡ [y | x <- [y | x <- m, y <- f x], y <- g x]
≡ [z | x <- m, y <- f x, z <- g y]
m >>= (\x -> f x >>= g)
≡ m >>= (\x -> [z | y <- f x, z <- g y])
≡ [y | x <- m, y <- (\x -> [z | y <- f x, z <- g y]) x]
≡ [y | x <- m, y <- [z | y <- f x, z <- g y]]
≡ [z | x <- m, y <- f x, z <- g y]

Maybe 是 Monad

instance  Monad Maybe  where
    return                    = Just
    (Just x) >>= k      = k x
    Nothing  >>= _      = Nothing
    Just _m1 >> m2      = m2
    Nothing  >> _m2     = Nothing
    fail _              = Nothing
Prelude> Just 9 >>= \x -> return (x*10)
Just 90
Prelude> do { x <- Just 9; return (x*10) }
Just 90
Prelude> Nothing >>= \x -> return (x*10)
Nothing
证明Maybe符合Monad法则:
1. return a >>= f ≡ f a
return a >>= f ≡ Just a >>= f ≡ f a
2. m >>= return ≡ m
Just x >>= return ≡ return x ≡ Just x
Nothing >>= return ≡ Nothing
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
(Just x >>= f) >>= g ≡ f x >>= g
(Nothing >>= f) >>= g ≡ Nothing >>= g ≡ Nothing
Just x >>= (\x -> f x >>= g) ≡ (\x -> f x >>= g) x ≡ f x >>= g
Nothing >>= (\x -> f x >>= g) ≡ Nothing

Either a 是 Monad

data  Either a b = Left a | Right b

instance Monad (Either e) where
    return        = Right
    Left  l >>= _ = Left l
    Right r >>= k = k r
Prelude> Left "boom" >>= \x -> return (x+1)
Left "boom"
Prelude> Right 3 >>= \x -> return (x + 100) :: Either String Int
Right 103
证明Either a符合Monad法则:
1. return a >>= f ≡ f a
return a >>= f ≡ Right a >>= f ≡ f a
2. m >>= return ≡ m
Right r >>= return ≡ return r ≡ Right r
Left l >>= return ≡ Left l
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
(Right r >>= f) >>= g ≡ f r >>= g
(Left l >>= f) >>= g ≡ Left l >>= g ≡ Left l
Right r >>= (\x -> f x >>= g) ≡ (\x -> f x >>= g) r ≡ f r >>= g
Left l >>= (\x -> f x >>= g) ≡ Left l

((->) r) 是 Monad

instance Monad ((->) r) where
    return = const
    x >>= f = \r -> f (x r) r
Prelude> (*2) >>= (\a -> (+10) >>= (\b -> return (a+b))) $ 3
19
Prelude> do { a <- (*2); b <- (+10); return (a+b) } $ 3
19
do { a <- (*2); b <- (+10); return (a+b) } $ 3 = (3*2)+(3+10) = 19
证明((->) r)符合Monad法则:
1. return a >>= f ≡ f a
return a >>= f ≡ const a >>= f ≡ \r -> f (const a r) r ≡ \r -> f a r ≡ f a 
2. m >>= return ≡ m
m >>= return ≡ \r -> return (m r) r ≡ \r -> const (m r) r ≡ \r -> m r ≡ m
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
(m >>= f) >>= g
≡ (\x -> f (m x) x) >>= g
≡ \r -> g ((\x -> f (m x) x) r) r
≡ \r -> g (f (m r) r) r
m >>= (\x -> f x >>= g)
≡ \r -> (\x -> \y -> g (f x y) y) (m r) r
≡ \r -> g (f (m r) r) r

fish operator 鱼形操作符
(>=>) 与 (<=<)

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
f >=> g = (\x -> f x >>= g)
(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)  
f <=< g = (\x -> g x >>= f)
两种Monad的结合运算

Monad的法则(2)

Left identity:	f <=< return ≡ f
Right identity:	return <=< f ≡ f
Associativity:	f <=< (g <=< h) ≡ (f <=< g) <=< h

Left identity:	return >=> f ≡ f
Right identity:	f >=> return ≡ f
Associativity:	f >=> (g >=> h) ≡ (f >=> g) >=> h
证明两种Monad法则等价:
1. return a >>= f ≡ f a 等价于 f <=< return ≡ f
f <=< return ≡ f
=> (\x -> return x >>= f) ≡ f
=> (\x -> return x >>= f) a ≡ f a
=> return a >>= f ≡ f a
2. m >>= return ≡ m 等价于 return <=< f ≡ f
return <=< f ≡ f
=> (\x -> f x >>= return) ≡ f
=> (\x -> f x >>= return) a ≡ f a
=> f a >>= return ≡ f a
=> m >>= return ≡ m
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) 等价于 f <=< (g <=< h) ≡ (f <=< g) <=< h
f <=< (g <=< h) ≡ (f <=< g) <=< h
=> f <=< (\x -> h x >>= g) ≡ (\x -> g x >>= f) <=< h
=> (\y -> (\x -> h x >>= g) y >>= f) ≡ (\y -> h y >>= (\x -> g x >>= f))
=> (\y -> h y >>= g >>= f) ≡ (\y -> h y >>= (\x -> g x >>= f))
=> (\y -> h y >>= g >>= f) a ≡ (\y -> h y >>= (\x -> g x >>= f)) a
=> h a >>= g >>= f ≡ h a >>= (\x -> g x >>= f)
=> m >>= g >>= f ≡ m >>= (\x -> g x >>= f)
=> m >>= f >>= g ≡ m >>= (\x -> f x >>= g)

反向 bind 操作符 (=<<)


(=<<)           :: Monad m => (a -> m b) -> m a -> m b
f =<< x         = x >>= f
Prelude Control.Monad> print =<< return 1
1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值