要約:Free モナドは何が嬉しいのかを議論するためのたたき台。以下の2つの論文に載っている例を3つの方法で実装する。
最近、僕はモナドを次のように説明するようにしている。「モナドとは言語内DSLを実装するための API (あるいはフレームワーク)」
だから、何か言語内DSLを作るなら、それをモナドのインスタンスにすべきだ。ここでは、getChar と putChar という API を持つ簡単な DSL を考える。この DSL を CharIO と呼ぼう。
当然、入出力なので IO の中で走るべきだが、表現と解釈は分離したい。
つまり getChar/putChar という表現と、解釈系を分離する。解釈系には
の2つを考える。後者は純粋だから、QuickCheck でテストする。
2つの点に注意:
Real World Haskell の 15 章には、型クラスで実装する方法が載っている。CharIO という型クラスのメソッドが getChar/putChar という訳だ。IO を CharIO のインスタンスにすれば、IO の中で走るし、純粋なモナドを CharIO のインスタンスにすれば、純粋に実行できる。それを実装したのがこのコード。
感想:
やはり何らかのデータ構造を定義して、それをモナドにしたい。その実装がこれ。
感想:
感想:
追記:DeriveFunctor 拡張を使えば、Functor の定義が不要になる。
どの方法でも、やりたいことは一応実装できる。「直接のモナド」を使ってもよいが、「Free モナド」だと、ほんの少しだけ簡単になる。他の利点は何だろう?