coqの基本tacticと生成コードとその解釈

例としてand除去を含む証明。

Coq < Goal forall A B : Prop, A /\ B -> B.
...
Unnamed_thm < intros.
1 subgoal

  A : Prop
  B : Prop
  H : A /\ B
  ============================
   B

Unnamed_thm < elim H.
1 subgoal

  A : Prop
  B : Prop
  H : A /\ B
  ============================
   A -> B -> B

...
Unnamed_thm < Save andelim.
intros.
elim H.
intros.
exact H1.
andelim is defined

これによってできる式を表示すると、

Coq < Print andelim.
andelim =
fun (A B : Prop) (H : A /\ B) => and_ind (fun (_ : A) (H1 : B) => H1) H
     : forall A B : Prop, A /\ B -> B


Argument scopes are [type_scope type_scope _]

Coq <

型関係を除去すると、amdelim = fun H => and_ind (fun _ H1 => H1) H というand_indに関数と引数のHを渡した式になっている。introsはfunをつけるものなので、戦略elim Hは、and_ind _ H.を生成するもののようだ。

and_indとはなにか。

Coq < Print and_ind.
and_ind =
fun A B P : Prop => and_rect (A:=A) (B:=B) (P:=P)
     : forall A B P : Prop, (A -> B -> P) -> A /\ B -> P


Arguments A, B, P are implicit
Argument scopes are [type_scope type_scope type_scope _ _]

Coq <

and_rectを呼んでいるだけの関数だが、コード上で明示されている引数は3つなので、さらに(A->B->P)とA/\Bの二つを引数に受け取ってPを返す関数を返しているとみなせる。で、and_rectは、

Coq < Print and_rect.
and_rect =
fun (A B : Prop) (P : Type) (f : A -> B -> P) (a : A /\ B) =>
match a with
| conj x x0 => f x x0
end
     : forall (A B : Prop) (P : Type), (A -> B -> P) -> A /\ B -> P


Arguments A, B, P are implicit
Argument scopes are [type_scope type_scope type_scope _ _]

Coq <

and_rectは、最後の引数aがconjパターンだったら、そのメンバー二つを引数にしてその前の引数の関数fを適用するものになっている。conjは

Coq < Print conj.
Inductive and (A : Prop) (B : Prop) : Prop :=  conj : A -> B -> A /\ B
For conj: Arguments A, B are implicit
For and: Argument scopes are [type_scope type_scope]
For conj: Argument scopes are [type_scope type_scope _ _]

Coq <

と、ここでand型が出てくる。conjはandのデータコンストラクタだった。これまでの関数や戦略は、以下のように解釈できる

  • and_rect: 引数A Bの関数をA/\Bを引数にとる関数に変える。いわば逆カリー化
  • and_ind: 戻り値もPropである and_rect
  • elim H: 二引数の関数goal:A->B->Pに、H: A /\ Bを分解して適用する。and型を2引数に分解する


逆にand導入を見てみる:

Coq < Goal forall A B : Prop, A -> B -> A /\ B.
...
Unnamed_thm < Save andintro.
intros.
split.
 exact H.
exact H0.
andintro is defined

でPrint

Coq < Print andintro.
andintro =
fun (A B : Prop) (H : A) (H0 : B) => conj H H0
     : forall A B : Prop, A -> B -> A /\ B


Argument scopes are [type_scope type_scope _ _]

Coq <

and導入のためのsplit戦略は、単にand型のコンストラクタコードconj _ _を生成するものだった。