ssreflect ライブラリ紹介(eqType編)
この記事はTheorem Proving Advent Calendar 2011の13日目の記事です。
ssreflectライブラリ紹介
この前はssreflectのtacticの紹介をやったので、ライブラリの紹介をします。ライブラリの概要は http://coqfinitgroup.gforge.inria.fr/ssreflect-1.3/ を見れば何か数学寄りだなというのが分かると思いますが、まあ完全に数学寄りです。しかもtrunkでは http://coqfinitgroup.gforge.inria.fr/ のように大変膨大になっております。
eqType
というわけで、一番根っこの部分にあるeqTypeを今回のメインにしましょう。
Coqを使い始めると、まあ誰でもこんな感じに書きたくなるでしょう。
Definition nat_gt0 := { x : nat | x > 0 }. Definition nat_gt1 := { x : nat | x > 1 }. Definition nat_gt0_succ : nat_gt0 -> nat_gt1 := (* うんたらかんたら *).
これにより、定義域を正の自然数に限定した関数 nat_gt0_succ が定義できました。プログラミングならこれでいいのですが、数学になると困ったことが起こります。例えば、この関数が単射であること:
Lemma nat_gt0_succ_inj : forall x y, nat_gt0_succ x = nat_gt0_succ y -> x = y.
これの証明は大変です。なぜかというと、xとyには各々が正であることの証明がくっついていますが、その証明が等しいことを示すのが困難だからです。すなわち、次のことを証明する必要があります。
Goal forall x (p1 p2 : x > 0), p1 = p2.
p1とp2はそれぞれxが正であることの証明で、それらが等しいことを示したいわけです。このように証明が等しいという性質をProof irrelevanceといいます。この問題の一番簡単な解決策は公理を導入することです。標準ライブラリの「Coq.Logic.ProofIrrelevance」を使うと「任意の命題がProof irrelevantである」が公理に追加されます。
ほとんどの場合で、この公理は不要です。eqTypeライブラリを使うとこの問題をほとんど解決してくれます。eqTypeは型クラスのようなもので、Canonical StructureというCoqの機能を使っています。まあほとんど型クラスのようなものです。eqTypeを実装した型Tは次の二つの値を持っています。
eq_op : T -> T -> bool. eqP : forall x y, reflect (x = y) (eq_op x y).
ここで、「reflect」は一つ目の命題と二つ目のbool値が同値であることを示します。すなわち、等値性を計算できるというのがeqTypeのもっている特長です。もちろん
eq_dec : forall x y, { x = y } + { x <> y }.
は上の二つと同値です。たったこれだけなので、導ける定理も少ないというか重要なのはただ一つだけで、「eq_irrelevance」はeqTypeを実装していれば、命題「x = y」はProof irrelevantであるになります。系として、
Lemma bool_irrelevance : forall (x y : bool) (p1 p2 : x = y), p1 = p2.
が得られます。よって、{ x : T | P x } の述語の部分を「f x = true」の形に書ける場合はこの型の値を簡単に比較できるわけです。ssreflectではbool -> PropのCoercionを「is_true」で定めているので、これは単に { x : T | f x } と書くことが出来ます。
subType
型 { x : T | f x } の持っているインターフェースを抽出した型クラスが subType になります。そして、eqTypeのsubTypeは自動的にeqTypeを実装します。他にもtupleとかmatrixなんかがsubTypeを使ってeqTypeを実装していたりします。
次回予告
次はchoiceライブラリ? exists x, P xから { x | P x }を取り出せる性質をもった型クラスを紹介するかも。