> {-# LANGUAGE DeriveFunctor #-} > import Control.Monad

Monad 的树型结构

我们来看一个二叉树 > data F a = E a | Fork (F a) (F a) > deriving (Functor) 它肯定是个 `Functor`。`Applicative` 的 `pure` 也好办。 > instance Applicative F where > pure = E > (<*>) = ap 我们 claim,`F` 也是个 `Monad`。`(>>=)` 要做什么呢?先随便写写吧。 > instance Monad F where `E` 好像是别无选择的 > E a >>= f = f a `Fork` 的话随便写写,一下就想到了这个 > Fork u v >>= f = Fork (u >>= f) (v >>= f) 写完了?但是这个靠谱么?

Monad 定律

- `return a >>= f = f a` - `m >>= return = m` - `(m >>= f) >>= g = m >>= (\x -> f x >>= g)` 如果用 `do` 写出来,看得更清楚 - `do { res <- return x; f res } = f x` - `do { res <- m; return res } = m` - `do { res <- do { x <- m; f x }; g res } = do { x <- m; res <- f x; g res }` 在命令式编程里面,你可能已经习惯于对程序做这种变换了。 在 Haskell 里,这种变换是可以**算**出来的。就用 Monad 定律。 我们来验证一下 F 符合 Monad 定律

第一条:

return a >>= f = E a >>= f = f a

第二条:

m >>= return = m 对 m 用归纳法 E a >>= return = return a = E a 给定 `u >>= return = u` 和 `v >>= return = v`,我们有 Fork u v >>= return = Fork (u >>= return) (v >>= return) = Fork u v

第三条

(m >>= f) >>= g 对 m 用归纳法 (E a >>= f) >>= g = f a >>= g (由 >>= 定义) = E a >>= (\x -> f x >>= g) (由 >>= 定义反推) 给定 `u` 和 `v` 符合条件,我们有 (Fork u v >>= f) >>= g = Fork (u >>= f) (v >>= f) >>= g (由 >>= 定义) = Fork ((u >>= f) >>= g) ((v >>= f) >>= g) (由 >>= 定义) = Fork (u >>= (\x -> f x >>= g)) (v >>= (\x -> f x >>= g)) (由归纳假设) = Fork u v >>= (\x -> f x >>= g) (由 >>= 定义反推) 感觉好像重复写了好多东西啊。有没有更一般的结构?

Free monad

> data Free f a > = W (f (Free f a)) > | Z a > deriving (Functor) 如果我们定义 > data Pair a = Pair a a > deriving (Functor) 那么 `Free Pair` 就和 `F` 是等效的了 Fork (Fork (E 2) (E 3)) (E 5) 对应 W (Bin (W (Bin (Z 2) (Z 3))) (Z 5)) 之前的这么一步 Fork u v >>= f = Fork (u >>= f) (v >>= f) `u` `v` 包在一个 `Pair` 里之后,后面的那个 `u >>= f` 和 `v >>= f` 就可以变成 `fmap (>>= f)` 了 > instance Functor f => Applicative (Free f) where > pure = Z > (<*>) = ap > instance Functor f => Monad (Free f) where > Z a >>= f = f a > W fa >>= f = W (fmap (>>= f) fa)

练习

- 证明 Free 是符合 Monad 定律的