在尝试证明引理时,我遇到这样一种情况,仅剩一个子目标,即nat
:
1 subgoal
...
______________________________________(1/1)
nat
我对这意味着什么感到困惑。 我实际上需要证明什么?是否有关于该主题的任何文档(对Coq的问题很难谷歌搜索)?
我不想分享实际的引理,因为这是一项任务。基本上,我试图证明一个归纳定义是这样的:
Inductive indef : deftype -> Prop :=
| foo x : indef (construct_0 x)
| bar a : (forall x, some_predicate x a) -> indef (construct_1 a).
作为证明,我可以证明(forall x : nat, some_predicate x a)
。虽然仅为some_predicate
定义了谓词nat
,但我怀疑问题与{{1}的定义中未明确指出x
的类型有关。 }}。
这可能是我看到indef
子目标`的原因吗?
答案 0 :(得分:1)
这里是一个示例,但我认为它不适合您的用例。我有一个产生逻辑语句证明的函数,但是此函数需要一个整数。该整数实际上对于证明没有用,但是由于键入原因,对该函数的任何使用都将需要该整数。
Definition my_fun (n : nat) : True := I.
Lemma dummy_setup : True.
Proof. apply my_fun.
因此,在这一点上,函数my_fun需要一个nat
类型的参数,该参数在其他任何地方都没有使用,但是它必须存在。 Coq系统处理此参数,就好像它是逻辑目的所需的证明一样,因此它要求您提供此类型的元素。通常,这表明您对函数的设计方式很差,并且它们使用了不使用的参数。避免这种情况的方法是回到引理,并确保它们没有无用的论点。
这是另一个例子。 my_trans
引理采用了无用的论点。
Require Import Arith.
Lemma my_trans : forall x y z t, x <= y -> y <= z -> x <= z.
Proof. intros x y z; apply (le_trans x y z). Qed.
使用此引理时,会弹出对额外参数的需求。证明机器只希望我证明存在某个自然数来填充该点。
Lemma toto x y z : y <= z -> x <= y -> x <= z.
intros h1 h2; revert h2 h1; apply my_trans.
您的问题的解决方案是查看定理,该定理的应用触发了该nat
目标的出现,并清理了该定理以删除实际上未使用的通用量化变量。
答案 1 :(得分:0)
只要引理的结果类型为Prop
,Coq就不会真正在证明过程中填充子目标。 通过填充子目标,您实际上是在提供该目标类型的值。
考虑一下:
如果遇到目标True
,则可以通过提供类型为True
的值I
来明确地实现目标。您可以用战术语言写:
1 subgoal
______________________________________(1/1)
True
exact I. (* explicit way, or *)
constructor. (* less explicit way *)
No more subgoals.
拥有nat
类型的目标是一回事。显然,O
是类型nat
的值(12432523547835
之类的自然数也是),因此您可以用它来实现目标:
1 subgoal
______________________________________(1/1)
nat
exact O. (* this obviously works *)
exact 12432523547835. (* this does work too *)
No more subgoals.
可能无关,但是目标或类型nat
或任何其他类型在“以证明模式编写定义”的上下文中完全有意义。例如一个函数
Definition double (x : nat) : nat := x + x.
可以用这种方式定义(但是不要这样做,除非目标类型是复杂的从属类型,并且结果不能以经典的方式轻易地得出):
Definition double (x : nat) : nat.
1 subgoal
x : nat
______________________________________(1/1)
nat
exact (x + x). (* Fill the goal with desired value *)
No more subgoals.
Defined. (* Use this instead of Qed to allow Coq to unfold the definition *)
Print double. (* Checking that the function body is correct *)
double = fun x : nat => x + x
: nat -> nat
我想我曾经在为一个可靠的递归函数编写证明时遇到过类似的情况,并且我以某种错误的假设(即所定义的函数,实际上不是假设)对目标进行了应用。但是我仍然可以完成证明,并且定义的功能可以按预期工作。