要約:Free モナドは何が嬉しいのかを議論するためのたたき台。以下の2つの論文に載っている例を3つの方法で実装する。
- Janis Voigtlander, "Asymptotic Improvement of Computations over Free Monads"
- Wouter Swierstra and Thorsten Altenkirch, "Beauty in the Beast -- A Functional Semantics for the Awkward Squad"
モナド
最近、僕はモナドを次のように説明するようにしている。「モナドとは言語内DSLを実装するための API (あるいはフレームワーク)」
だから、何か言語内DSLを作るなら、それをモナドのインスタンスにすべきだ。ここでは、getChar と putChar という API を持つ簡単な DSL を考える。この DSL を CharIO と呼ぼう。
当然、入出力なので IO の中で走るべきだが、表現と解釈は分離したい。
つまり getChar/putChar という表現と、解釈系を分離する。解釈系には
- 実際に IO の中で走らせる
- 副作用を発生させずに走らせる
の2つを考える。後者は純粋だから、QuickCheck でテストする。
2つの点に注意:
型クラス
Real World Haskell の 15 章には、型クラスで実装する方法が載っている。CharIO という型クラスのメソッドが getChar/putChar という訳だ。IO を CharIO のインスタンスにすれば、IO の中で走るし、純粋なモナドを CharIO のインスタンスにすれば、純粋に実行できる。それを実装したのがこのコード。
感想:
直接のモナド
やはり何らかのデータ構造を定義して、それをモナドにしたい。その実装がこれ。
感想:
- データ型に本質でない Pure という構成子が必要なのでちょっと嫌。
- 純粋に走らせる方は、簡単に書けた。