Open10
Coqに入門してみる
ここを使う:
和訳版もあったけど微妙に古かった。Coq自体はopam on WSL2でインストールした。
IDEはEmacs上のProof GeneralとスタンドアロンのCoqIDE(Coq付属)が書かれていたが、慣れ親しんだVSCode(+拡張機能vscoq)でやってみる。
Basics
-
Inductive day : Type :=
のType
は何だろ(無くても推論されるっぽい)- ⇒ 多相型は
Inductive list (X:Type) : Type :=
みたいに定義。依存型もできそう - ⇒ 帰納的な命題も
Inductive
を使って定義(e.g.Inductive ev : nat -> Prop := ...
)。(IndProp参照)
- ⇒ 多相型は
- 呪文のように出てくる
Proof. simpl. reflexivity. Qed.
- ⇒
simpl
は両辺の計算を進める(無くてもreflexivity
がやってくれる)。reflexivity
は両辺が等価かチェックする(反射律)。
- ⇒
-
Example hoge :=
でなくExample hoge :
。=
が付いていてもExample自体はエラー出ない(Proofでエラー出る)- ⇒ 定理名はその定理の証明(proof object)を参照しており、言明自体は定理名の型である。なので(?)、
:=
でなく:
。カリー・ハワード対応。(ProofObjects参照) -
Theorem hoge :=
などExample以外での:=
はエラー。Exampleは真でなくてもいいから?
- ⇒ 定理名はその定理の証明(proof object)を参照しており、言明自体は定理名の型である。なので(?)、
- Notationはマクロではない?
-
(b0 b1 b2 b3 : bit)
- ⇒
(b0 : bit) (b1 : bit) (b2 : bit) (b3 : bit)
の略記
- ⇒
-
True
はPropでtrue
はbool- ⇒ Logic#Propositions vs. Booleansとその次で違い・利点欠点の説明有り
-
forall n
に対してintros m
でもいいのは先頭から埋めてくから?- ⇒ そうっぽい。名づけをしている感じ(仮定
H
はその後の証明で「H
」で参照できる)
- ⇒ そうっぽい。名づけをしている感じ(仮定
- 含意の左辺(仮定)がFalseだった場合に直接含意をTrueに判定できるtacticありそう
- ⇒
discriminate
tacticが使える。(Tactics#The injection and dicsriminate Tactics参照) - ⇒
H: False
に対してdestruct H
で、サブゴールが0になるのでQED.(Logic#Falsehood and Nagation参照)
- ⇒
- 組み込みの比較演算子は?
- ⇒
From Coq Require Import Arith.Arith.
すれば<=?
などが使える
- ⇒
Indcution
- Exercise mul_comm ちょっと詰まった。サブ定理で量化するか否かの違いだった
- ⇒ Tactics#Varying the Induction Hypothesisでそれに近いことが解説されてる
- 定義済みの定理一覧欲しい
- ⇒
Search (_ + _ = _ + _).
などで定理検索可(List#Search参照)
- ⇒
- 関数の中身見たい
- ⇒
Compute <関数名>
で見れる(再帰がfix使ってたり関数が展開されてたりはする) - ⇒ それよりも
Print <関数名>
で正に中身を見れる。
- ⇒
Lists
- 任意長のリストもNotationできるの面白い
-
n + 1
をS n
に書き換えるのは、可換(add_comm)を示せばrewrite add_comm. simpl.
でいける(加算の定義は左辺でmatchingしてるので具体的な項を左辺に持ってくればsimplificationできる)
Poly
-
Inductive list' {X:Type} : Type :=
としたときの問題- ⇒
X
が具体的に判明していようがいまいがlist'
で表示されるcons' 1 nil' : list'
(nil' : @list' nat) : list'
nil' : list'
- c.f.
nil: list ?X
,(nil : list nat) : list nat
- ⇒
- 扱いの違い
-
Compute nil.
→= nil : list ?X
-
Check nil.
→nil : list ?X where ?X : [ |- Type]
-
Definition mynil := nil.
→The following term ...
-
Tactics
-
generalize dependent x
のdependent
は何?- ⇒
x
に依存するものも移動させるらしい
- ⇒
Logic
-
H: ~ P
をdestructすると、現在のゴールを無視してP
というサブゴールだけになる- ⇒
P
がTrueであることを示せれば、H
はFalseすなわちcontradiction。
- ⇒
-
apply H1. apply H2. apply H3
をapply H1 H2 H3
みたいに書けないか(rewrite
も)- ⇒
apply H1, H2, H3
でいけた
- ⇒
-
/\
と\/
は右結合、なぜ?- ⇒ splitで左から1つずつはがせる
- ⇒ 証明の自動化の際に利便性がわかりやすい。左から1つずつleftを試して剥がしていける(Imp#Coq Automation参照)
- tr_rev_correct少し詰まった。
tr_rev l
(すなわちrev_append l []
)は特殊な形なので、より一般的な形にした言明を示してそれを適用する。 - excluded_middle_irrefutableは本当に試行錯誤。
- 必要なassertionは複雑なものではなくとてもシンプルなもの。
-
H: P \/ ~P -> False
はassertionの証明にも使うし、assertionを証明した後にももう一回使う。
- classical_axiomsも試行錯誤。
- 含意のループを作れとヒントがあるけど、それでさえループの候補は
通りもある。結局、とりあえず成り立ちそうな含意を片っ端から示していくのがよい。5!/5 = 24 -
A -> B
を示したいときに「仮定にA
だけじゃなくてC
もあればいけるのにな」となったら、とりあえずA /\ C -> B
を示して、そのあと別にA -> C
も示せれば、両者からA -> B
が示せる。
- 含意のループを作れとヒントがあるけど、それでさえループの候補は
IndProp
- 仮定
H: S n <= S m
をinductionしたときの第1ケースで仮定n = m
(ないしはS n = S m
)は生成されないが、inversionすればn = m
は生成される- ⇒
S n
とS m
をrememberすればinductionでもいける(IndProp#The remember Tactic参照)
- ⇒
- subseq_trans、試行錯誤を経て何とか解けた。何で?
-
H1: P
とH2: P -> Q
があるときにapply H2 in H1
するとH1
が消えてしまう。(backwardでやればいいのでは? ⇒Q
がexists x, ...
の形の場合x
を文脈に持ってくるためにはforwardでないとだめそう。)仮定を複製する組み込みtacticない?(assertしたり自前でP -> P /\ P
を用意すればいけるけど)- ⇒
apply H2 in H1 as H1'
でいいじゃん
- ⇒
- 証明中に脈絡なく
thm: P \/ Q
を使って場合分けしたい場合はdestruct thm
すればよい- ⇒ 一般に、脈絡なく
thm: P
を仮定に持ってきたいときはassertすればよい
- ⇒ 一般に、脈絡なく
- inversionすると名づけられない等式が生成されることがある
- ⇒ 等式らは
[EQ1 EQ2]
のようにまとめてあげることで名づけられる
- ⇒ 等式らは
- 鳩の巣原理の問題中のrepeatsは問題説明が良くない気がする。「要素がrepeatしている」はその要素が連続している印象があるけど、ここでは連続している必要はない。どちらかと言えばduplicates。
- asciiのbool比較は
eqb
、そのPropへの反映はeqb_spec
(調べた)。これ使わなくても行けるのか...? -
x <> y
にsymmetryを使いたい
Maps / ProofObjects / IndPrinciples / Rel
特になし
Imp
-
Set Printing Implicit.
とは
Auto
-
Hint Transparent
とは
ImpCEvalFun / ImpParser / Extraction
特になし
Volume 1 読了。
- ある程度Coqを扱えるようになった。
- 上のコメント量の差の通り、IndPropsまでは時折立ち止まることが多かった一方それ以降はスムーズに進められた。
- 関数型言語に触れたことのある人にとっては、序盤は関数型言語一般の話も割とあるのでやや冗長ぎみ。
- ProofObjectsとIndPrinciplesは、Recommended pathには入ってないけど読んでおいた方がいい気がする。
- 主だった概念の紹介はImp前までで、Imp以降は応用・自動化の話。