Monadic Reflectionについて
kontlang作成の一つの目標は、この資料を元に:
モナドをつくれるようにしてみたい、というものだった。
結果的にMaybe、ListやStateモナドを「つくって」みたのだが。
そもそもこのつくったものは本当にモナドなのか?という疑問が湧いてきた。
挙動はHaskellのdo
記法に非常に近いが、微妙に違いもあるし、そもそもモナドとはreturn
とbind
があるものなのでは?
というわけで「モナドをつくろう」の参考資料であるAndrzej FilinskiのRepresenting Monadsと、同じ著者によるMonadic Reflection in Haskellを読んでみた。
Representing Monadsの「5 Implementation and Examples」を見たところ:
(letfn [reflect [m] (shift [k] (bind m k))] ...) (let [reify (macro [expr] (reset (return expr)))] ...)
という定義で特定のモナドのbind
とreturn
、そしてshift
とreset
があればreify
とreflect
は書ける。
そして論文には出てないようだがreify
とreflect
があればreturn
とbind
は書ける:
(letfn [return [a] (reify a)] ...) (let [bind (macro [m f] (reify (reflect (f (reflect m)))))] ...)
というわけでbind
とreturn
、reify
とreflect
の間にはかなり密接な関係がある。bind
とreturn
はreify
とreflect
だけで定義できるのに対し、reify
とreflect
はbind
とreturn
に加えてshift
とreset
が必要なことを考えるとreify
とreflect
のほうが強力なようだ。
reify
とreflect
とは、モナドのAPIであるbind
とreturn
と同程度以上の表現力(?)を持ち、専用のdo
構文などを用意せずともdirect styleでモナディックなコードを書けるようにする関数(あるいはマクロ)ということになるだろうか。
というわけで、たしかにreify
とreflect
を実装しておけばとりあえず「モナドをつくった」と言えそうである。よかったよかった。