■
アルゴリズムが、Rewriting ruleの形で与えられています。
a
- -
c
みたいな感じ。aとかの集合Eがあって、Eの中に書き換えられるものが無くなったら停止、というアルゴリズム。
こういうのどうやって書いたら良いんでしょうか。
ありがちなのは、まだ解けてない集合Eと解いた後の集合E'を渡すようにして、Eで書き換えたものをE'に加えていって、Eが空になったら終了、という感じだと思います。しかし、今回はEの書き換えをEからE'の書き換えに変形するのが自明ではないので、やりたくないのです。
苦し紛れに書いたのはこんな感じのコード。
exception Solved of E.t let rec solve es = let try_solve es e = (* eを書き換えられる規則があったら、書き換えた後の集合を返す *) (* なかったら、そのまま返す *) in try E.iter (fun e -> let es' = try_solve es e in if not (E.equal es es') then raise (Solved es')) es; es with Solved es -> solve es
E.iterでそれぞれの要素に対して「解けないか試してみて、解けたら例外を投げて解ける式でなかったらそのまま放置」という関数を適用し、例外を拾って再帰的に呼び出す、とうコード。Camlらしく、imperativeに書いてみようかとも思いましたが、やっぱりうまくかけない気がしたのでこっちで。
しかし、こうやって書いてみると、悪くないような気もするようなしないような。(遅そうですが。)(あとでリファクタリングすることにしようと思います。)