command foo :: X -> Y throws [E1, ..., Ek]
reads [a1, ..., ap]
updates [b1, ..., bq]
uses [c1, ..., cr]
refers example:impl;
X, Y, E1, ..., Ek は型ですが、a1, ..., ap, b1, ..., bq, c1, ..., cr はファシリティと呼ばれるAPIプロバイダの名前です。ほとんどの場合、ファシリティはストレージアクセスを提供します。
話を簡単にするために、次の形を考えることにします。
command foo :: X -> Y throws E
reads a
updates b
uses c
refers example:impl;
X, Y, Eは型なので、値の集合(領域)を持ちます。その集合も同じ文字 X, Y, E で表します。a, b, c は、対応する状態の集合(状態空間)を持ちます。それらを A, B, C で表します。Aはリードオンリーですが、BとCはコマンドから変更可能です。しかし、直接変更するのではなくて、更新リクエストを発行します。Bを更新するリクエストの集合をM、Cを更新するリクエストの集合をNとしておきます。MとNはモノイドになります。
以上の記法を使うと、コマンドfooは、X×(A×C) → E + Y×(M×N) という写像でモデル化できます。メインストリームの入出力 X → Y 以外に、AとCという2つの状態空間を参照し、例外Eを出す可能性を持ち、MとNという2つのモノイドの要素であるリクエストを発行します。精密なモデル化では、コマンドfooをもっと小さな粒度の単位に切り刻みますが、それはまーいいとしましょう。
コマンド宣言の各節は、次のものを記述しています。
節 | モナド類の種別 | モノイド積 | モノイド類の種別 |
---|---|---|---|
throws 節 | 例外モナド | 直和 | 余対角モノイド |
reads 節 | 参照コモナド | 直積 | 対角コモノイド |
updates 節 | 更新モナド | 直積 | 更新モノイド |
uses 節 | 参照更新両モナド | 直積 | 対角更新両モノイド |
各節が表していることは、メインストリーム入出力以外に、コマンドが使用するスタンピング・{モナド, コモナド, 両モナド} だったのです。これらのスタンピングは、一般化クライスリ圏を定義します。そして、コマンドのモデルは、構成された一般化クライスリ圏のなかに取られます*2。
つまり、コマンド宣言は、そのコマンドのイデアがどこに棲んでいるかを表現しているわけです。