Don';我不理解Coq中假设`(存在x:x,~px)`的“破坏”策略
我是Coq的新手,尝试着从中学习。在“Coq中的逻辑”一章中,有一个练习Don';我不理解Coq中假设`(存在x:x,~px)`的“破坏”策略,coq,coq-tactic,Coq,Coq Tactic,我是Coq的新手,尝试着从中学习。在“Coq中的逻辑”一章中,有一个练习not\u exists\u 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]. - ap
not\u exists\u 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.
之后呢
em: excluded_middle
X: Type
P: X -> Prop
x: X
F: ~ P x
--------------------------------------
(1/1)
exists x0 : X, ~ P x0
虽然我理解假设中的
p/\code>和p\/Q
上的destruct
,但我不理解它是如何在p->False
上工作的。通常,destruct t
适用于t
是归纳类型I
的居住者,为可能用于生成t
的I
的每个可能构造函数提供一个目标。如您所述,这里的H
具有类型P->False
,这不是归纳类型,而是False
。所以发生的是:destruct
为您提供了与P
假设H
相对应的第一个目标。将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.
您将在*目标*
中看到:
1 subgoal (ID 77)
A, B, C : Prop
H : A
H0 : C
H1 : A ∨ B → B ∨ C → A ∧ B
============================
A ∧ B
好的,我们需要显示A/\B
。我们可以使用split
来分解和分离,因此我们需要显示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。让我们看看destructh1
对我们的目标有什么作用:
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
为了完整性:(没有拆分;尝试假设速记)
另一种查看方式是:H1是一个函数,它将a\/B
和B\/C
作为输入<代码>析构函数
对其输出起作用。为了破坏这样一个函数的结果,您需要给它一个适当的输入。
然后,destruct
在不引入额外目标的情况下执行案例分析。
我们也可以在验证脚本中执行此操作,然后再进行销毁
ing:
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.
从证明术语的角度来看,a/\B
的destruct
与match a/\B with conj H1 H2=>(*构造一个以您的目标为其类型的术语*)end
相同。
我们可以用相应的refine
来替换校对脚本中的destruct
,该脚本正好做到:
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.
回到你的证据上来。你在销毁之前的目标
em: excluded_middle
X: Type
P: X -> Prop
H: ~ (exists x : X, ~ P x)
x: X
F: ~ P x
--------------------------------------
(1/1)
P x
应用不在H中展开策略后,您会看到:
em: excluded_middle
X: Type
P: X -> Prop
H: (exists x : X, P x -> ⊥) -> ⊥
x: X
F: ~ P x
--------------------------------------
(1/1)
P x
现在回想一下⊥: 它是一个不能被构造的命题,也就是说,它没有构造函数。
如果你有⊥ 作为一种假设,您可以进行分解,您基本上可以查看匹配的类型⊥ 使用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.
无论如何,destruct
在您的假设下,H
将为您的目标提供证明,如果您能够显示存在x:x,~px->⊥代码>
除了destruct
,您还可以执行exfalso。应用H.
实现同样的效果。谢谢,现在我知道p->Q
上的析构函数实际上是Q
上的析构函数,并将p
作为子目标添加。如果Q
是False
像这里一样,原始目标从exfalso开始消失,因此只剩下子目标P
有待证明。谢谢你的详细解释,我从你的答案中学到了一些新东西:-)。如果理解正确,P->Q
上的destruct
告诉coq我想Q
上的destruct
,coq将P
作为子目标添加为预目标。
em: excluded_middle
X: Type
P: X -> Prop
H: (exists x : X, P x -> ⊥) -> ⊥
x: X
F: ~ P x
--------------------------------------
(1/1)
P x
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))