関数プログラミングの楽しみ
大変いい本だと思う。関数プログラミングって何、ということを概説している。
本の内容としては、主としてHaskell界隈で著名な研究者たちが、関数プログラミングにまつわるちょっとしたコネタ(といっても論文になったような内容)を集めたエッセイ集といったところ。なのでトピックとしては多岐にわたっており、扱っている内容も様々、それぞれ。データ構造に関するものもあれば、Arrowのような構造に関する議論もあり、ハードウェア記述言語のようなアプリケーションよりのトピックもある。
だけど、本書を通じて一貫したスタイルというか、傾向のようなものがある。これこそが「関数プログラミング」ってことなのかもしれない。読んでいてそんなふうに思った。
思えば、オブジェクト指向プログラミングというのも得体のしれないものだ。この日記を読んでいるプログラミングよりの人はオブジェクト指向ぐらいはだいたい分かっていると思うけれど、いざとなったときに人に説明できるだろうか。昔ながらの解説書には、たとえばカプセル化と継承と多態性、なんて言葉が書かれていて、生物の分類を移し変えたようなものがあって、それでなんとなくわかったような気になるのだが、そういうものを読んでからプログラムを書いてみたところでオブジェクト指向のプログラミングスタイルになるわけでもない。こういう説明は間違ってはいないのだが、プログラミングスタイルの解説としては適切なものではない。
オブジェクト指向でプログラムを書く上で必要なこととか考えなければいけないこととか、恥ずかしながらぼくは大して言語化できないのだが、実際にはいろんな人が言語化を試みており、それはそれなりに成功を収めているような気がする。いずれにせよ、オブジェクト指向というのはプログラミングのスタイルとか方法論であって、プログラミング言語に依存するものではないというところで合意が取れていると思う。
関数プログラミングも似たようなものだ。
高階関数とか参照透明性とか、術語はいろいろあるけれど、じゃあそういうものを使えば関数プログラミングなのかというとどうも違う。関数プログラミングも同じように方法論であり考え方なのだが、方法論の記述は決定的に足りていないような気がする。オブジェクト指向の解説に生物の分類を持ってくるのがピンと来ないように、関数プログラミングの解説にフィボナッチ数の計算を持ってきても、どうにもごまかされているような気分がする。
この本にあるのが、その方法論の実例なのではないだろうか。私が読んで面白かったのは、どちらかといえばアプリケーションよりの6章「金融取引契約の書き方」や8章「Lava: 関数によるハードウェア記述」、11章「もっと整ったプリティプリンタ」だが、このみっつには共通点があって、ある程度の実用性のあるコードであること(解決している問題がトイでない)と、共通した問題解決手法を採用していることである。
その問題解決手法というのが、プリミティブとコンビネータの組み合わせだ。プリミティブというのは非常に単純な処理を行うような単純要素で、金融取引なら「ある人にある金額を支払う」だとか、ハードウェア記述なら単純な論理回路だとか、非常に単純な記述である。コンビネータというのはプリミティブとプリミティブを組み合わせる演算のことで、金融取引なら「AまたはBを遂行する」だとか「期日AまでにBを遂行する権利をもつ」だとか、ハードウェア記述なら論理回路同士の結線パターンだとかに対応する。
プリミティブはそれ自体が単純なものなので、プリミティブに対する処理は難しいものではない。コンビネータも組み合わせ方はそれぞれさほど複雑なものではなく、充分シンプルに記述できる。ところがプリミティブにコンビネータを組み合わせることによって、実用に足るぐらい複雑な記述も可能になる。コンビネータ同士を組み合わせることで複雑なパターンも形成できるし、一旦定義してしまえば複雑なパターンも単純なコンビネータも等価に扱うことができる。このへんが関数プログラミングのメリットだろうか。
こういった問題への取り組み方や解決方法は数学屋さんがやりそうな手法であり、Haskell界隈のコミュニティでこういう手法が取られるというのは自然に思える。けれども、実世界で起こりうるような規模の問題に対してきちんと向きあって、それなりの成果を挙げているのが本書で扱っている面白いところだ。もちろん、処理速度的に効率がいいとか悪いとか、そういうことまでは本書では踏み込んでいないし、実際に実世界に対応するにはいろいろと泥臭いコードが必要になるとぼく個人は思っている。
だがここでぼくが言いたいのは、問題に対するこうしたアプローチそのものが「関数プログラミング」ということなのではないか、ということだ。単にカプセル化したり継承したりすればオブジェクト指向なのではないように、単に再起するとか高階関数を使うだけで関数プログラミングになるわけではない。考え方を変えて、問題への取り組み方を変えることで、はじめて関数プログラミングの地平が見えてくる。そうして初めて、こういうアプローチの良し悪しが議論できるのではないかと思う。
そういう考え方への導入として良書だと思う。