読者です 読者をやめる 読者になる 読者になる

Karakuriの導入(0) -状態をぶった切る!-

あるとき、私は思った――

「Getter、Setterと、状態を次に進める関数を持つ何かがほしい!そうすればゲームやユーザーインターフェイスなどがとても書きやすくなるのに……!」

私はそれをカラクリと名付けた。存在するかどうかわからない理想の構造を求めて…

オブジェクトの型をKとしよう。型A, Bに対するGetterが存在するならば、以下の関数が存在することになる。

getA :: K -> A
getB :: K -> B

ここで積の性質を思い出そう。K -> (A, B)があればgetA、getBは自明だ。つまり、Getterは一つで十分ということになる。次に、X, YのSetterを考えよう。

setX :: X -> K -> K
setY :: Y -> K -> K

和の性質により、Either X Y -> K -> Kが存在すれば、setX, setYの定義は自明になるので、Setterも一つで十分だ。そして、状態を更新する関数はK -> m Kとなる。それらを一つの型に詰め込むことでKarakuriが完成する。

data Karakuri m a b = Karakuri
    { look :: b
    , feed :: a -> Karakuri m a b
    , step :: m (Karakuri m a b)
    }

Karakuriはムーアマシンに相当し、lookは出力を取り出す関数、feedとstepは状態遷移にあたる。

KarakuriはApplicativeになるが、その仕組みはとても簡単だ。pure aはaを出すKarakuriになり、fを出力するKarakuriと、aを出力するKarakuriを(<*>)で合成するとf aを出力するKarakuriになる。

このKarakuriを使えば、状態が隠蔽されているが、一部分だけ制御できるオブジェクトが作れるのだ。次回はこれをもっと簡単に扱うためのモナドを導入してみよう。