Upload
tmiya
View
1.263
Download
0
Embed Size (px)
DESCRIPTION
Talk at "Coq Party", 2010/Nov/27, Nagoya, Japan.
Citation preview
定理証明器 Coq と 証明付き DSL
2010/11/27 @tmiya_
あなたがCoqを学ぶべき理由
2
どう考えても成り立つのは自明だけど、 総当たりで示すには状態爆発してしまう
テストで発見出来るのは間違いだけ。 正しい事は保証出来ないよ
網羅性のあるテストを書くのも、 何回も実施するのも大変だ
そんなあなたには証明駆動開発。 正しいと証明されたコードを生成。
全ケースを網羅しないと証明通らない。 一度証明したらテストは不要。
まさに定理証明系向きの課題。 正しい事を証明しよう。
最近はDSLが流行っているようだけど オレオレ言語に信頼性あるのかなぁ?
正しさを保証する言語処理系を作るには定理証明系を使うのが一番
Domain Specific
Languages
3
ドメイン固有言語 • Domain Specific Languages • 特定分野のタスクの為に作られた言語 • 利点
– 問題領域に適した抽象化、用語を使用 – 読みやすい/書きやすい/ドキュメントの代わり
• 自然言語より簡潔かつ厳密に記述可能 • スクリプト言語(Ruby, Pythonなど)が使われる事多い
– 安全性 • 利用範囲を超えた機能は提供されない
• それだけで満足?正しさをどう担保する? – DSLで書かれたものの正しさ。DSLそれ自体の正しさ。
• “Mechanized metatheory: ready for prime time?” (ICFP 2010) – http://www.cis.upenn.edu/~bcpierce/wmm/wmm10/cheney.pdf – これまで:既にあるもの(言語とか)を定理証明系で検証 – これから:定理証明系の存在を前提に言語のデザイン(例えば次の
XQueryとか)
金融商品DSL • 発端
– 2010/4/7 : SECが金融商品を明確に記述する為に、自然言語ではなくPythonを使う事を提案
– なぜPython?もっと相応しい物があるのでは?例えば… • 型付き関数型言語:型検査でDSLの安全性を担保可能
– 「金融取引契約の書き方」(Simon Peyton Jones and Jean-Marc Eber) • 書籍「関数プログラミング言語の楽しみ」 • 金融取引はコンビネータを組み合わせて記述可能。
– 規格にあるものしか書けない金融商品 XML (FpML) は仕様が肥大化するしか無い。
• Haskellでライブラリ記述。 • 後にLexiFi社のMLFiに
• ACMよりのSECへのコメント – http://www.sec.gov/comments/s7-08-10/s70810-89.pdf – 「Pythonより適切な言語がある。静的型検査可能でsandboxがあるものが良
い」 – 「専用の適切なDSLあるいはライブラリを開発すべき」 – まぁ当然の解答と言える
AURA:認可•監査論理の言語 • 論文:“AURA: A Programming Language for Authorization and Audit” (2008 ICFP)
• 「~は~をしても良い」を記述するDSL – 依存型のある言語では静的型検査で証明を扱える ⇒ 「コンパイル時に」アクセス権限有無を判定可能 – 権限委譲は関数合成(モナド)として表現可能
• AURAの実装 – ある種の型付きλ計算として定義 (1.4k LOC) – soundness, decidability を Coq で証明 (6k + 5k LOC)
⇒ AURA言語の正しさを証明 – F#での実装が入手可能
• http://www.cis.upenn.edu/~stevez/sol/aura.html
Compcert Verified Compiler • http://compcert.inria.fr/ • Coqで証明されたC言語コンパイラ
– Compcert C ⇒ PowerPC • Cのsubset : longjmp/setjmpとか一部サポートされない
– 生成されたコードは元のCコードと等価である事を証明 – 実用を考えた最適化:gcc ‒O1並みの速度
• 将来の応用
7
Program Prover
Model Checker Sta3c Analyzer Other Language
Clight
Cminor
External vs Internal • 外部DSLの話 : AURA
– 汎用的なプログラミング言語とは別に、DSL言語を作る • 単なるXMLファイルという場合もあるが • コードジェネレーションなんかもここに入る
– どうせならCoqとかを使って言語の正しさを証明したい – Operational Semantics : とりあえずTAPL勉強中
• Ott : そういうツールがあるらしい。使い方を覚えたいなぁ。
• 内部DSL : 金融商品コンビネータの話 – 汎用プログラミング言語自体をDSLとして使える様にする
• 世間での評価「古くはLispで、最近はRubyとかで」 • Haskellで内部DSLに、という話は昔から多い。(最近はScalaも割と) • 要するにプログラム言語っぽく無くて、自然言語や専用言語っぽければOK
• CoqでDSLってどうだろう? – 実はCoqは向いているのでは?
Coq as a DSL Host Language
9
記法を定義出来る (1) • Coqではユーザ定義の記法を使える Notation "A /\ B" := (and A B) (at level 80, right associativity).
• 表示のときも使ってくれる Coq < Check (and True False). True /\ False : Prop
• 記号の意味を探すときはLocate Coq < Locate "/\". Notation Scope "A /\ B" := and A B : type_scope (default interpretation)
10
演算子 優先度
\/ 85(低)
/\ 80
~ 75
=, <>, <, >, <=, >=
70
+, -, || 50
*, /, && 40
- (単項の-) 35(高)
これを参考に
記法を定義出来る (2) • 単項演算子、mix-fixな演算子もOK : かなりDSLっぽくなる Notation "~ x" := (not x) (at level 75, right associativity). Notation "’IF’ c1 ’then’ c2 ’else’ c3" := (IF_then_else c1 c2 c3). Notation "{ x : A | P }” := (sigA (fun x => P)) (at level 0, x at level 99).
• 推論して欲しい場合は@を付けないと(使用時に)エラー Notation "x = y" := (@eq _ x y) (at level 70, no associativity).
• 定義と一緒に記法を定義出来る Fixpoint plus (n m:nat) {struct n} : nat := match n with | O => m | S p => S (p+m) end where "n + m" := (plus n m).
11
記法を定義出来る (3) • パーサコンビネータと組み合わせて使っている例
http://www.seas.upenn.edu/~cis500/current/sf/html/ImpParser.html Notation “‘DO’ ( x , y ) <-- e1 ;; e2 ‘OR’ e3” := (match e1 with | SomeE (x,y) => e2 | NoneE err => e3 end) (right associativity, at level 60, e2 at next level).
• 使っている例 Fixpoint parsePrimaryExp (steps:nat) symtable (xs : list token) : optionE (aexp * list token) := match steps with | 0 => NoneE "Too many recursive calls" | S steps' => DO (i, rest) <-- parseIdentifier symtable xs ;; SomeE (AId i, rest) OR DO (n, rest) <-- parseNumber xs ;; SomeE (ANum n, rest) OR (DO (e, rest) <== firstExpect "(" (parseSumExp steps' symtable) xs;; DO (u, rest') <== expect ")" rest ;; SomeE(e,rest')) end
12
記法を定義出来る (4) • 繰り返しのあるパターン : .. を使って繰り返しを再帰的に表現出来る
– 可変長引数みたいなものを扱いたいときは便利 Coq < Notation "[ x ; .. ; y ]" := (@cons _ x .. (@cons _ y (@nil _) ) .. ). Setting notation at level 0.
Coq < Check ([1 ; 2 ; 3]). [1; 2; 3] : list nat
• 実は下記でもOK Coq < Notation "[ x ; .. ; y ]" := (cons x .. (cons y nil) ..). Setting notation at level 0.
13
記法定義の落とし穴 • えっ?定義が無いの?本当? Coq < Locate "->". Unknown notation
• 定義出来た!? Notation "A -> B" := (and A B) (at level 80, right associativity).
• 本当に定義が上書きされたのか? Coq < Lemma test : True -> True. test < intros. 1 subgoal ============================ True -> True (* 変化が無い *) test < split. 2 subgoals ============================ True (* and なので split される *) subgoal 2 is: True
• Locate信用出来ない。重要な予約語の上書きには注意。 14
Tacticの定義の方法 CPDTに載っているTactic定義の例 (p.217)
Coq < Ltac my_tauto := Coq < repeat match goal with Coq < | [ H : ?P |- ?P ] => exact H Coq < | [ |- True ] => constructor Coq < | [ |- _ /\ _ ] => constructor Coq < | [ |- _ -> _ ] => intro Coq < | [ H : False |- _ ] => destruct H Coq < | [ H : _ /\ _ |- _ ] => destruct H Coq < | [ H : _ \/ _ |- _ ] => destruct H Coq < | [ H1 : ?P -> ?Q, H2 : ?P |- _ ] => Coq < let H := fresh “H” in (* Hなんとかみたいな新しい名前をつける *) Coq < generalize (H1 H2); clear H1; intro H Coq < end. my_tauto is defined repeatを外したmy_tauto1を作って、何度も適用すると動作の具合が良く解る
…これって、DSLに使えない? • パターンマッチとかどう見ても高機能なんだが…
15
Ltac定義の中で出来る事 • 順次処理(expr1; expr2) • 繰り返し(repeat expr)(do num expr) • ローカル定義(let) • パターンマッチ(match) • 計算(eval redexpr in term) • メッセージ表示(idtac msg_token … msg_token) • 外部呼び出し(external “command” “request” tacarg…)
– 元々、外部の定理証明器を呼び出す為の機能 – XML形式で外と通信出来る – これを使って外部コマンドを実行出来たらどうか? – 例えば “ls” コマンドを実行して、ファイルリストをCoqに返せたら? – makeの真似事ぐらい出来そうな…
と、考えてみたんですが、そこで行き詰まりました。 • Coq内部とかOcamlに詳しい人が引き継いでくれるといいなぁ… • 気をつけないと矛盾をCoqに持ち込んでFalsoみたいになるかも…
16
まとめ • Domain Specific Languages
– やっぱり正しさが証明されているDSLを使いたいですよね。 – ならばCoqでDSLを。
• Coq as a DSL Host Language – CoqのNotation定義で自由なDSL記法を – Tacticから外部コマンド実行とか出来ると、色々出来るんじゃないかな?
17