2015-05-26 空腹関数からオブジェクト

連日雑記。2 日も続くなんて明日も地震が起きてしまう。

毎週月曜の TaPL 読みも 20 章「再帰型」に来た。20 章なんて遠いなと思ってたけど、難しい定義とかすっ飛ばしてトピックだけ拾い読みしてるから早い。しかし理解度としてはぬるめ。まあそれでも面白いところはいっぱいある。

今日読んで面白かったところは空腹関数からオブジェクトまでの流れ。空腹関数は f 0 1 2 3 ... というふうに引数を無限に受け付ける関数で、ひとつ引数を受け取るとまたひとつ引数を受け取れる関数を返す。空腹関数は不動点演算子を使って定義できる。パクパク引数を食べまくるパクパク。

こういう構造を見るとストリームになりそうと思うよね。はい、ちゃんと定義されている。ストリームは空腹関数と同じように引数として unit を受け取り、何らかの数とストリームの組を返す関数として定義されている。この組の第一要素を head、第二要素のストリームを tail とみることができる。例では upfrom0 という 0 からの無限な整数列を定義している。

ストリームを一般化したプロセスというものもある。ストリームでは unit を受け取っていたが、ある数を受け取れるようにし、数と新たなプロセスを返すものをプロセスと呼ぶ。例えば今まで入力された数の総和を返すようなプロセスがあるとする。2 を渡すと {今までの総和に2を足した数, 新しい総和を返すプロセス} というような組が返る。この組の第二要素のプロセスに 3 を渡すと、{今までの総和に 2 を足した数に 3 を足した数, 新しい総和を返すプロセス'} という組が返ってくる。TaPL では第二引数の新しいプロセスに数を送る send という関数と、第一引数の値を取り出せる curr (current?)を定義しており、下記のようなことができる。

curr (send 20 (send 3 (send 5 process)));
# => 28 : Nat

第二要素の 新しいプロセス というものについて考えてみるとこれは状態を表しているようにも思える。最近は FRP が話題だったような気もするので(もう古い話題?)、ストリームといったら状態とピンとくる人も多いかも。

はい、ここでオブジェクトが出てくる。プロセスで、第一要素に何らかの数が入っているとしていた部分をレコードにしてあげれば、純粋関数的なオブジェクトを表すことができる。例えばレコードのフィールドとして定義されている関数で、increment のような状態を変える関数は、次の状態のオブジェクトとプロセスを返す。このようにして状態の変わるオブジェクトを表すことができる。かっこいい。

文だけだとよく分からないと思うので TaPL の定義を見たほうが早い(定義を書くとほぼ TaPL の写しになってしまうので文で書いてみた)。状態を変える関数が複数定義されているオブジェクトがあって、その状態の無限の遷移(無限に深い木)を想像すると夜も良く眠れそうな気がする。


ここまで書いてからストリームからオブジェクトの話は SICP にもあったなぁというのを思い出した。すぐ思い出せないといけないな。

http://sicp.iijlab.net/fulltext/x355.html