※ 引述《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