例如,
Lemma ex_1:
exists n, n=1.
Proof.
显示一个子目标:
exists n : nat, n = 1
econstructor命令将目标更改为
?n = 1
可以获取的命令
exists n : nat, n = 1
还是从“?n = 1”开始?
或者,我们证明了为此存在(存在n,〜)形式的一些难题。 我们怎样才能“应用”这个难题?
答案 0 :(得分:2)
温特豪德(ThéoWinterhalter)提出了一些适用于这种情况的策略,但总的来说,econstructor
在某些意义上不是可逆的。
econstructor
可以将两个不同的证明状态带到相同的结束状态。这就是说,econstructor
在证明状态上不是内射性的。例如,考虑这种(相当愚蠢的)情况。
Inductive exists': Prop :=
| intro (n: nat): n = 1 -> exists'.
Goal exists'.
Proof.
econstructor.
即使起始目标(在econstructor
之前不同),我们也以完全相同的结束状态结束。
econstructor
通常会丢失信息。即使我们知道原始状态是什么,也可能无法恢复原状。在此示例中,我们将使用标准库中的inhabited
,但它对exists
也同样有效,因为inhabited A
等效于exists a: A, True
。
Goal forall A: Type, inhabited A -> inhabited A.
Proof.
intros A H.
econstructor.
现在证明状态为
1 subgoal
A : Type
H : inhabited A
______________________________________(1/1)
A
,我们想使用H
来解决这个目标。但这(通常)是不可能的。我们不能仅仅从声明A
类型的元素存在并生成A
类型的实际项开始。问题在于,由于H
是Prop
,如果目标也是Prop
,我们可以销毁(或匹配)它。使用econstructor
之后,情况就不再如此,因此我们必须有类型A
的显式见证。在您的示例中,此方法可行,因为我们确切知道nat
的哪个元素满足n = 1
,但总的来说,我们不知道
证明助手Lean uses的通用语句forall A, nonempty A -> A
(nonempty
与Coq的inhabited
相同)为其经典逻辑库提供了动力。 Coq中排除中间作品的相同证明(假设功能可扩展性和命题可扩展性)。因此,如果我们有forall A: Type, inhabited A -> A
,则可以证明排除中律,甚至选择公理的某些强形式(加上一些可扩展性公理)。
还要注意,当您使用econstructor
时,任何存在变量最终都必须使用 current 上下文中存在的值实例化。如果您有H: exists n: nat, n = 1
,则必须在使用H
之前破坏econstructor
。。
Hypothesis H: exists n: nat, n = 1.
Goal exists n: nat, n = 1.
Proof.
destruct H as [x H].
econstructor.
exact H.
Defined.
Goal exists n: nat, n = 1.
Proof.
econstructor.
destruct H as [x H].
Fail exact H.
Abort.
答案 1 :(得分:0)
如果有假设
H : exists n : nat, n = 1
您可以使用
destruct H as [n Hn]
获得假设
n : nat
Hn : n = 1
这就是您使用这样的信息的方式。
对于问题的另一部分,我需要看一个您正在尝试做的例子。在这里,您使用econstructor
(也可以是eexists
),以便在您的上下文中获得一个存在变量?n
,然后将通过 unification 对其进行求解。
例如,您然后用?n = 1
来解决reflexivity
,这是1 = 1
的证明,因此Coq知道?n
必须是1
。
您还可以更加精确,并使用exist
策略直接给证人。
exists 1. reflexivity.