Coqにおいて「等しい」をあらわす述語eq
の,反射律・対称律・推移律を証明します.
これらを2つのアプローチ「matchを使う」と「eq_indを使う」で証明してみます.
各種定義
Coqのeq
は次のように定義されています.
Inductive eq (A : Type) (x : A) : A -> Prop := eq_refl : x = x
eq x y
をx = y
とするNotationを使っています.
この定義をすると次のeq_indも証明されます.
eq_ind : forall (A : Type) (x : A) (P : A -> Prop),
P x -> forall y : A, x = y -> P y
eq_indの証明
まずはeq_ind
の証明をmatch
を使って行います.
fun (A : Type) (x : A) (P : A -> Prop) (H : P x) (y : A) (H1 : x = y) =>
match H1 in (_ = z) return (P z) with
| eq_refl => H
end
: forall (A : Type) (x : A) (P : A -> Prop), P x ->
forall y : A, x = y -> P y
eq
の証明をmatch
するには,in (_ = z)
というのをつければよいようです.
これを使って対称律・推移律の証明を調べてみましょう.
反射律
次のように証明できます.
fun (A : Type) (x : A) => eq_refl x
: forall (A : Type) (x : A), x = x
対称律
対称律の主張を以下に示します.
forall (A : Type) (x y : A), x = y -> y = x
matchを使った証明
次のように,eq_refl x
を使います.
fun (A : Type) (x y : A) (H : x = y) =>
match H in (_ = z) return (z = x) with
| eq_refl => eq_refl x
end
: forall (A : Type) (x y : A), x = y -> y = x
eq_indを使った証明
eq_ind
の仮定をひとつずつ準備して,証明します.
fun (A : Type) (x y : A) (H : x = y) =>
eq_ind x (fun z : A => z = x) (eq_refl x) y H
: forall (A : Type) (x y : A), x = y -> y = x
推移律
推移律の主張を以下に示します.
forall (A : Type) (x y z : A), x = y -> y = z -> x = z
matchを使った証明
次のように,y=z
を分解して,x=y
のy
をz
にします.
fun (A : Type) (x y z : A) (H1 : x = y) (H2 : y = z) =>
match H2 in (_ = a) return (x = a) with
| eq_refl => H1
end
: forall (A : Type) (x y z : A), x = y -> y = z -> x = z
2019-12-08追記 次の記事で考察されています
http://kyasmt.hatenablog.com/entry/20091214/1260801722
eq_indを使った証明
上のmatch
を使った証明をeq_ind
を使って書き直した感じです.
fun (A : Type) (x y z : A) (H1 : x = y) (H2 : y = z) =>
eq_ind y (fun a : A => x = a) H1 z H2
: forall (A : Type) (x y z : A), x = y -> y = z -> x = z
まとめ
等号の3つの性質をCoqで定式化し,証明を行いました.Coqでは等号が帰納的に定義されていて,3つの性質それぞれはCoqによって証明される定理だとわかりました.
次のようなことがわかりました..
- 学生のときに,「同値関係」を「反射的かつ対称的かつ推移的」と習います.等号にこのような性質があるのは自明ですが,私には引っかかっていました.今回,より原理原則といえる部分を確認できました.
- 「等号を帰納的に定義する」「
match
の型付けが少し複雑」「eq_ind
は証明できる」ということが明確になりました.