Software Foundations
Logic.v
証明オブジェクトが良くわからん。
論理積の交換で、Logic.vに載ってるやり方だと以下のような証明オブジェクトが作られる。
Theorem and_commut : forall P Q : Prop, P /\ Q -> Q /\ P. Proof. intros P Q H. inversion H. split. apply H1. apply H0. Qed. Print and_commut. (* and_commut = fun (P Q : Prop) (H : P /\ Q) => (fun H0 : Q /\ P => H0) match H with | conj H0 H1 => (fun (H2 : P) (H3 : Q) => conj Q P H3 H2) H0 H1 end : forall P Q : Prop, P /\ Q -> Q /\ P *)
作られた、証明オブジェクトがどうなってるのかというレベルで(どれが関数の引数で、本体で、というレベルで)良くわからん。
(fun H0 : Q /\ P => H0) は何だろう?
- Q/\P型の命題の証明を受け取ってそのまま返す関数
- その関数に、match式で作った、Q/\P型の命題の証明をそのまま渡す。
でいいのか?
また、コンテキストに、
P : Prop
H : P
のようにある場合、Pは命題。 Hは、命題Pの証明(根拠)。であってるんだっけ。大丈夫そうだな。
inversionではなく、destructを使用して証明すると、ずっとすっきりした証明オブジェクトが作られる。
こちらはなんとか分かる。気がする。
Theorem and_commut' : forall P Q : Prop, P /\ Q -> Q /\ P. Proof. intros P Q H. destruct H. apply conj. apply H0. apply H. Qed. (* これくらいなら、destructでも問題ない *) Print and_commut'. (* and_commut' = fun (P Q : Prop) (H : P /\ Q) => match H with | conj H0 H1 => conj Q P H1 H0 end : forall P Q : Prop, P /\ Q -> Q /\ P *)