※ 引述《suhorng ( )》之铭言:
: 不过那个结构[aka. data Free f a = Pure a | Impure (f (Free f a))]
: 到底要怎么推出来呢...?
我觉得若能用 "monad is monoid in the category of endofunctors"
这个观点把 free monoid 和 free monad 类比起来,应该会比较直觉。
(警告:本文论述和正式理论有显著差距。)
先从 monoid 和 monad 的类比开始。我们知道 monoid 是有单位元素和
二元乘法(具结合律)的集合。对应到 monad 时,我们得问这个“集合”
是什么,以及这“集合”里的“元素”如何“相乘”。(单位元素请自行脑补。)
这里需要一点想像力的飞跃:给定 monadic functor M, 我们可以把 M
想成一个 type, 里面的元素是“一层 M-结构”。例如,定义
data Expr a = Var a | Add (Expr a) (Expr a)
Expr 是个 monad. 什么是“一层 Expr-结构”?考虑 Expr Int:
这是在整数上加一层“Expr-结构” —— 整数并非赤裸裸地出现,
而是包在某个树形里。这个树形可能是 Var -(减号代表为了包东西留的洞),
可能是 Add (Var -) (Var -), 或更复杂的东西。这些用来包东西的树形
可直观视为 Expr 这个 "type" 的元素。(如果你觉得这个说法有漏洞,
你大概懂了...)
那么“Expr-结构”相乘是什么意思?是两层树形整并成一层树形,即
join :: Expr (Expr a) -> Expr a
join (Var e) = e
join (Add es es') = Add (join es) (join es')
若树形里面包的东西(都)是树形,那么整个形状可“视为”一个更大的树形。
“整并”有结合律:若树形里包树形,后者里面再包树形,那么把这三层整并成
一层时,先整并外两层或内两层,结果都一样。
至此我们已可对照 monoid 和 monad —— 我们把 join 的型态写成
"point-free style"
join :: (Expr . Expr) ~> Expr