coqでの証明戦略の引数って何?

例は、forall (A B: Prop), A->(A->B)->B。

これはintrosをすると、A, A->B ┣ Bとなる。これはcoqでは自動的に解決できるものであり、証明戦略的には、->除去である。

によるとapplyする状況なのだが、仕組みを認識していないと引数に何を指定するかわかりにくい。

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

  A : Prop
  B : Prop
  H : A
  H0 : A -> B
  ============================
   B

Unnamed_thm < 

正解はapply H0。

Unnamed_thm < apply H0.
1 subgoal

  A : Prop
  B : Prop
  H : A
  H0 : A -> B
  ============================
   A

Unnamed_thm <

これで、左辺がgoalに入れ替わる。

結果は

intros A B H H0.
apply H0.
exact H.

これらの証明戦略とは、A,Bを変数の型、->を関数の型とみる、Curry–Howard対応でのプログラム視点では、コード生成マクロのようになっている。Ltacコマンドで定義もできる。そのtactic定義言語は以下のページに仕様がある:

証明結果の戦略列はそのマクロの適用順に並べてる。その適用結果後はLemmaやTheoremもDefinition同様の名前付関数になる。

コマンド 適用結果
0 Goal 〜 _: forall (A B: Prop), A->(A->B)->B
1 intros A B fun (A B:Prop) => _: A->(A->B)->B
2 intro H fun (A B:Prop) => fun (H:A) => (_:(A->B)->B)
3 intro H0 fun (A B:Prop) => fun (H:A) => (fun (H0:A->B) => (_:B))
4 apply H0 fun (A B:Prop) => fun (H:A) => (fun (H0:A->B) => (H0 (_:A)))
5 exact H fun (A B:Prop) => fun (H:A) => (fun (H0:A->B) => (H0 (H)))
6 Save myfunc myfunc = fun (A B : Prop) (H : A) (H0 : A-> B) => H0 H

論理式分解としては逆っぽい意味にみえるのtacticも、コード生成的視点でみればそれっぽく見える点に注目したい。


GoalやLemmaで証明したものは、Printをすると、上記の関数のほうで表示される。

Coq < Print Unnamed_thm.
Unnamed_thm =
fun (A B : Prop) (H : A) (H0 : A -> B) => H0 H
     : forall A B : Prop, A -> (A -> B) -> B

Coq <

coqではGoalやLemmaやTheoremでは直接本体の式を書くことはできないが、Definitionでは本体を書かないとGoalやLemma同様の証明モードにはいり、証明によって式を定義することができる。