このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

ミーリー/メイヤー・モデル

僕はメイヤー先生のファン

それはいいとして、メイヤー流のクエリー/コマンド・スタイルでプログラムを書いても何も不便はない。クエリーでもコマンドでもない関数/メソッドが必要なら便利関数として書けばいいだけ。

それで、Erlangに対してメイヤー方式を定義したい。

ミーリー機械

モデルとしてミーリー機械(Mealy machine)を採用する。ミーリー機械の状態遷移を

  • (s, a) -> (s', b)

の形で書く。aが入力、s, s'が状態、bが出力。遷移は S×A×S×B = A×(S×S)×B = S×(A×B)×S の部分集合となる。

Vを値(と呼ばれる何か)の集合として、{val(x) | x∈V} の形の記号を出力Bに入れておく。また、εを無音記号とする。すると:

  • クエリーは (s, q) -> (s, val(x)) の形の遷移
  • コマンドは (s, c) -> (s', ε) の形の遷移

ということになる。メイヤーによれば、たいていの便利関数は (s, c) -> (s', ε); (s', q) -> (s', val(x)) として実現できる。せいぜい、cの前後の状態 s, s' から計算できる程度に限定すべき。

Erlangのメッセージ生成関数は、(s, g) -> (s', m) の形になる。これもコマンドとみなしてよいが、出力が無音ではないので、ジェネレータと呼ぶことにする。

ミーリー/メイヤー・モデル

ミーリー機械(初期状態集合を持つ)Mをモデルとする。
Mのクエリーは、遷移ではなくて、状態空間上の関数だとする。コマンドは (s, c) -> (s', ε) の形の遷移、ジェネレータは (s, c) -> (s', m) の形の遷移だとする。

クエリー、コマンド、ジェネレータを関数で表現すると:

  1. クエリー:引数に状態を渡す、戻り値は値(value
  2. コマンド:引数に状態を渡す、戻り値は状態(state)
  3. ジェネレータ:引数に状態を渡す、戻り値は状態(state)、副作用が生成メッセージ列。

クエリーとコマンドは単なる関数で、何も細工する必要がない。ジェネレータでは、?send(To, Term) というマクロを必ず使うことにして、sendマクロが例えばプロセス辞書に書きこむ。戻り値である状態とメッセージ列を組にして返すラップを作ればよい。

関数が例外を出したときは、それを記録するので、次のようなデータを持つことになる。

  1. Value = {value, term()} | no_value
  2. State = term()
  3. Message = [{To, term()}]
  4. Exception = {Class, term(), Stacktrace} | no_exception

http://erlang.g.hatena.ne.jp/m-hiyama/20090331/1238463293 も参照。