言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

モナドは僕たちにどういう影響を与えるか?

正月早々風邪でしんどくて、全く仕事が出来ない状態が続いています。年始から色々イベントがてんこ盛りなのに申し訳ないです。一日の半分くらい寝て、半分くらい仕事に関係無い事しています。

モナドが僕たちにどういう影響を与えるかについて書きます。ようやく Haskell の IO やリストが使えるようになったばかりなのに気が早いですが、新しい事を理解するには、まずそれがどういう物であるのかを予想して、勉強した後にどのくらい近いかを見るほうが、最初から白紙の状態から始めるよりは楽です。だから間違っていても仮定から始めたほうがよいのです。ここでの仮定は、モナド関数型言語だけに特別便利なアイデアではなくて、僕たちのホームグラウンドであるオブジェクト指向、まあスクイークにも必要な物だという話です。

ここから下は全部仮定の話です。オブジェクト指向の生み出した素晴らしいアイデアの利点は、情報のつながりをコードにそのまま記述できるようにした事です。画面にある沢山のアイコンやウインドウを、オブジェクト同士が交信するモデルで見事に抽象化する事が出来ます。ある瞬間コンピュータ上に起こっている事を、オブジェクト指向は分かりやすく表現する事が出来ます。問題は、これを時間軸上に拡張した時に起こります。

ここで具体的な分かりやすい例が書ければカッコイイのですが、まだ考え中です。個人的には、動的スプレッドシートの開発、Croquet の開発、eToys の開発などで、時間と空間双方の関わる構造を抽象化(まとめて入れ子可能にする事)する際に同じような困難を感じました。例えば eToys では、1 秒ごとに10m 歩進む車をまとめて 10 回実行しようとするときに、それは10 秒時計を進ませる事なのか 1 秒中に100 m 進むようにするのかを一般的な方法で表現する方法が無いです。もちろんそれをパラメータ化する事は簡単ですが、それをさらに大きなプログラムの一部にしようとする時に安易なパラメータ化はすぐに破綻してしまいます。

時間と空間に限らず、何となく関連しているのに注意深く分けて扱わなくてはならない物は意外と多いです。例えば集合とその要素。亀が100匹それぞれ歩いているとしてその100匹の動きは一匹ずつ亀の動きで表現出来ます。だけど100匹を一匹として扱ってよいかと言うとそうではなくて、やっぱり100匹の場合は途中で脱落する亀の事を考えなくてはいけなかったり、色々気を使うのです。この「気の使い方」が、先ほどの車の例と似ているなーと思っているのですが、どこが似ているかずっと謎でした。

モナドはこの一見関係なさそうな数々の問題に共通の枠組みを与えます。モナドを図示するとすれば、液体の流れるホースをどのように繋ぐかという問題になると思います。ホース(皮)は集合であったり時間だったりします。中の液体はデータ自体です。プログラマが出来るのは、液体が流れてきた際にどのように扱うか(車や亀をどう進めるか)と、ホースの繋ぎ方(車の時間的変化や亀の集合)だけで、例えばホースを壊したり別の液体を流したりという事は許されていません。

オブジェクト指向は生物学的なメタファから生まれたと聞きます。オブジェクトは細胞で、メッセージが細胞膜を通過する物質の流れです。このメタファに従ってモナドを考えると、それは消化器系や循環器系と言ったより大きな流れの構造とみる事が出来るでしょう。部分と全体を同じ論理で扱えない際に、モナドはその境界を明快にし、部分で可能な事、全体で可能な事、部分と全体がどのように交わるかを決定します。

モナドHaskell の制限から生まれた物なので、最初から副作用のあるオブジェクト指向言語の応用を考えるのはナンセンスな気もしますが、モナドが明確にした問題の重要さ(特に、逐次実行と集合の map を同じ演算子でやるというのにびっくりしました)、は一般的な物として考えられると思います。