Coq:目标只是一种类型(当使用带有不必要参数的定理时)
Coq: goal is just a type (when using theorems with unnecessary arguments)
我在 Coq 中发现了一个奇怪的怪癖。当你有一个带有不必要参数的定理时,就会发生这种情况,我们对这个定理使用 rewrite
。例如,考虑以下代码片段。
Theorem foo : forall (k : nat) (x : bool), k=0+k.
Proof. reflexivity. Qed.
Theorem bar : forall (k : nat), 0+k=k.
Proof.
intros k. rewrite foo. reflexivity.
(* At this point, the goal is just "bool"! *)
Abort.
在这个例子中,foo
有一个多余的参数 x
。然后,当我在 bar
的证明中使用 rewrite foo
时,它会生成一个目标,它只是读取“bool
”。
我的第一个问题是:为什么会产生这样的目标?
其次,我发现可以使用 assumption
策略来完成此目标。但是,这并没有真正说明目标是如何解决的。还有什么战术可以用来完成这样的目标?
目标 bool
是在您应用 rewrite foo.
策略时创建的。
此时,您要求 Coq 找到表达式 ek : nat
和 ex : bool
,以便 foo ek ex
的左侧出现在目标中。使用合一,Coq 推断出 ek := k
是一个合理的选择,但是它没有得到 ex
的任何信息,因为变量 x
没有出现在 foo
的陪域中。因此,它创建了一个新目标,以便您作为用户可以将缺少的参数填充到 foo
.
现在,由于该参数实际上未被使用,您可以通过多种方式实现该目标:您可以提供具体的布尔值 exact true.
或 exact false
,将其留给自动化 constructor.
或使用您在上下文中拥有的任何布尔值(实际上我对假设的行为感到有点惊讶是您的上下文已关闭,如您的示例所示)。
您还可以在 Coq 创建目标之前提供参数,例如使用 rewrite (foo k true).
。
kyo 很好地回答了您的问题,但我记得对此感到困惑,所以这里有一些额外的背景信息:
在 Coq 中,说 X
成立(比如,这是一个目标,现在它被证明了)等同于说存在一个 X
类型的项(即 X
有人居住)。当X
恰好是一个逻辑公式时(即当X : Prop
时),我们期望找到它作为目标并用策略来证明它。当 X
碰巧是其他任何东西时(例如,bool
),我们希望找到它作为一个术语并在定义中使用它。但是,没有什么可以阻止您在定义中使用逻辑公式(通常导致依赖类型),通过显式提供证明而不是使用策略(例如 eq_refl : 0 = 0
)来证明逻辑公式,或者证明 [=16] =] 居住在使用战术。
这种区别仍然有用,因为我们通常不关心 哪个 证明被用来证明给定的定理,但我们经常关心哪个类型的术语 bool
我们掌握了(虽然不是在你的例子中)。
我在 Coq 中发现了一个奇怪的怪癖。当你有一个带有不必要参数的定理时,就会发生这种情况,我们对这个定理使用 rewrite
。例如,考虑以下代码片段。
Theorem foo : forall (k : nat) (x : bool), k=0+k.
Proof. reflexivity. Qed.
Theorem bar : forall (k : nat), 0+k=k.
Proof.
intros k. rewrite foo. reflexivity.
(* At this point, the goal is just "bool"! *)
Abort.
在这个例子中,foo
有一个多余的参数 x
。然后,当我在 bar
的证明中使用 rewrite foo
时,它会生成一个目标,它只是读取“bool
”。
我的第一个问题是:为什么会产生这样的目标?
其次,我发现可以使用 assumption
策略来完成此目标。但是,这并没有真正说明目标是如何解决的。还有什么战术可以用来完成这样的目标?
目标 bool
是在您应用 rewrite foo.
策略时创建的。
此时,您要求 Coq 找到表达式 ek : nat
和 ex : bool
,以便 foo ek ex
的左侧出现在目标中。使用合一,Coq 推断出 ek := k
是一个合理的选择,但是它没有得到 ex
的任何信息,因为变量 x
没有出现在 foo
的陪域中。因此,它创建了一个新目标,以便您作为用户可以将缺少的参数填充到 foo
.
现在,由于该参数实际上未被使用,您可以通过多种方式实现该目标:您可以提供具体的布尔值 exact true.
或 exact false
,将其留给自动化 constructor.
或使用您在上下文中拥有的任何布尔值(实际上我对假设的行为感到有点惊讶是您的上下文已关闭,如您的示例所示)。
您还可以在 Coq 创建目标之前提供参数,例如使用 rewrite (foo k true).
。
kyo 很好地回答了您的问题,但我记得对此感到困惑,所以这里有一些额外的背景信息:
在 Coq 中,说 X
成立(比如,这是一个目标,现在它被证明了)等同于说存在一个 X
类型的项(即 X
有人居住)。当X
恰好是一个逻辑公式时(即当X : Prop
时),我们期望找到它作为目标并用策略来证明它。当 X
碰巧是其他任何东西时(例如,bool
),我们希望找到它作为一个术语并在定义中使用它。但是,没有什么可以阻止您在定义中使用逻辑公式(通常导致依赖类型),通过显式提供证明而不是使用策略(例如 eq_refl : 0 = 0
)来证明逻辑公式,或者证明 [=16] =] 居住在使用战术。
这种区别仍然有用,因为我们通常不关心 哪个 证明被用来证明给定的定理,但我们经常关心哪个类型的术语 bool
我们掌握了(虽然不是在你的例子中)。