![](/img/trans.png)
[英]How to destruct a function (like H : ~ (forall x : X, p x)) in Coq?
[英]Don't understand `destruct` tactic on hypothesis `~ (exists x : X, ~ P x)` in Coq
我是 Coq 的新手,並嘗試通過軟件基礎來學習它。 在“Coq 中的邏輯”一章中,有一個練習not_exists_dist
,我完成了(通過猜測)但不明白:
Theorem not_exists_dist :
excluded_middle →
∀ (X:Type) (P : X → Prop),
¬ (∃ x, ¬ P x) → (∀ x, P x).
Proof.
intros em X P H x.
destruct (em (P x)) as [T | F].
- apply T.
- destruct H. (* <-- This step *)
exists x.
apply F.
Qed.
在destruct
之前,上下文和目標如下所示:
em: excluded_middle
X: Type
P: X -> Prop
H: ~ (exists x : X, ~ P x)
x: X
F: ~ P x
--------------------------------------
(1/1)
P x
之后
em: excluded_middle
X: Type
P: X -> Prop
x: X
F: ~ P x
--------------------------------------
(1/1)
exists x0 : X, ~ P x0
雖然我理解destruct
on P /\ Q
和P \/ Q
在假設中,但我不明白它是如何在P -> False
上工作的,就像這里一樣。
通常,當t
是歸納類型I
的居民時, destruct t
應用,為I
的每個可能的構造函數提供一個目標,這些構造函數可以用來產生t
。 正如您所說,這里H
的類型為P -> False
,這不是歸納類型,但False
是。 所以會發生這樣的事情: destruct
給你一個對應於H
的P
假設的第一個目標。 將H
應用於該目標會導致False
類型的術語,這是一種歸納類型, destruct
可以正常工作,因為False
沒有構造函數,所以給你零目標。 歸納類型的許多策略都是這樣工作的,假設形式為P1 -> … -> Pn -> I
,其中I
是歸納類型:它們為您提供P1
... Pn
的輔助目標,然后對I
進行操作。
讓我通過先做另一個證明來嘗試給出一些直覺。 考慮:
Goal forall A B C : Prop, A -> C -> (A \/ B -> B \/ C -> A /\ B) -> A /\ B.
Proof.
intros. (*eval up to here*)
Admitted.
您將在*goals*
中看到的是:
1 subgoal (ID 77)
A, B, C : Prop
H : A
H0 : C
H1 : A ∨ B → B ∨ C → A ∧ B
============================
A ∧ B
好的,所以我們需要顯示A /\ B
。 我們可以使用split
將 and 分開,因此我們需要顯示A
和B
。 A
很容易通過假設得出, B
是我們沒有的東西。 因此,我們的證明腳本現在可能如下所示:
Goal forall A B C : Prop, A -> C -> (A \/ B -> B \/ C -> A /\ B) -> A /\ B.
Proof.
intros. split; try assumption. (*eval up to here*)
Admitted.
有目標:
1 subgoal (ID 80)
A, B, C : Prop
H : A
H0 : C
H1 : A ∨ B → B ∨ C → A ∧ B
============================
B
我們可以到達B
的唯一方法是通過某種方式使用 H1。 讓我們看看destruct H1
對我們的目標做了什么:
3 subgoals (ID 86)
A, B, C : Prop
H : A
H0 : C
============================
A ∨ B
subgoal 2 (ID 87) is:
B ∨ C
subgoal 3 (ID 93) is:
B
我們得到了額外的子目標! 為了破壞 H1,我們需要提供A \/ B
和B \/ C
的證明,否則我們不能破壞A /\ B
!
為了完整起見:(沒有split;try assumption
簡寫)
Goal forall A B C : Prop, A -> C -> (A \/ B -> B \/ C -> A /\ B) -> A /\ B.
Proof.
intros. split.
- assumption.
- destruct H1.
+ left. assumption.
+ right. assumption.
+ assumption.
Qed.
另一種查看方式是:H1 是一個 function,它以A \/ B
和B \/ C
作為輸入。 destruct
在其 output 上工作。 為了破壞這樣一個 function 的結果,你需要給它一個適當的輸入。 然后, destruct
在不引入額外目標的情況下執行案例分析。 我們也可以在destruct
之前在證明腳本中這樣做:
Goal forall A B C : Prop, A -> C -> (A \/ B -> B \/ C -> A /\ B) -> A /\ B.
Proof.
intros. split.
- assumption.
- specialize (H1 (or_introl H) (or_intror H0)).
destruct H1.
assumption.
Qed.
從證明術語的角度來看, destruct
A /\ B
與match A /\ B with conj H1 H2 => (*construct a term that has your goal as its type*) end
。 我們可以將證明腳本中的destruct
替換為相應的細化,該refine
正是這樣做的:
Goal forall A B C : Prop, A -> C -> (A \/ B -> B \/ C -> A /\ B) -> A /\ B.
Proof.
intros. unfold not in H0. split.
- assumption.
- specialize (H1 (or_introl H) (or_intror H0)).
refine (match H1 with conj Ha Hb => _ end).
exact Hb.
Qed.
回到你的證明。 destruct
前的目標
em: excluded_middle
X: Type
P: X -> Prop
H: ~ (exists x : X, ~ P x)
x: X
F: ~ P x
--------------------------------------
(1/1)
P x
在應用unfold not in H
策略后,您會看到:
em: excluded_middle
X: Type
P: X -> Prop
H: (exists x : X, P x -> ⊥) -> ⊥
x: X
F: ~ P x
--------------------------------------
(1/1)
P x
現在回想一下⊥的定義:它是一個不能被構造的命題,即它沒有構造函數。 如果您以某種方式將 ⊥ 作為假設並且您進行了破壞,那么您基本上會查看match ⊥ with end
的類型,它可以是任何東西。
事實上,我們可以用它證明任何目標:
Goal (forall (A : Prop), A) <-> False. (* <- note that this is different from *)
Proof. (* forall (A : Prop), A <-> False *)
split; intros.
- specialize (H False). assumption.
- refine (match H with end).
Qed.
它的證明是:
(λ (A B C : Prop) (H : A) (H0 : C) (H1 : A ∨ B → B ∨ C → A ∧ B),
conj H (let H2 : A ∧ B := H1 (or_introl H) (or_intror H0) in match H2 with
| conj _ Hb => Hb
end))
無論如何,如果您能夠證明exists x: X, ~ P x -> ⊥
destruct
根據您的假設H
將為您的目標提供證明。
除了destruct
,你也可以做exfalso. apply H.
exfalso. apply H.
來達到同樣的目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.