我从Coq开始,发现我必须提供使用List.remove
的可判定平等的证明。 e.g。
Require Import Coq.Lists.List.
Import List.ListNotations.
Inductive T : Set := A | B | C.
Lemma eq_dec : forall a b : T, {a = b} + {a <> b}.
Proof.
destruct a, b; try (left; reflexivity); try (right; congruence).
Qed.
Definition f (xs : list T) : list T := List.remove eq_dec A xs.
现在进行类型检查,但我不明白如何使用它。
Theorem foo : f [ A; B; C ] = [ B; C ].
Proof. reflexivity.
给了我
Error: Unable to unify "[B; C]" with "f [A; B; C]".
这种可判定的平等如何发挥作用以及我能读到的有关它的一些好消息来源?
我刚刚了解了decide equality
战术,
解决了
forall x y:R, {x=y}+{~x=y}
形式的目标,其中R是一个 归纳类型,使其构造者不采取证据或 函数作为参数,也不依赖于依赖类型中的对象。
所以eq_dec
可以重写:
Lemma eq_dec : forall a b : T, {a = b} + {a <> b}.
Proof. decide equality. Defined.
我刚刚了解了Scheme Equality for T
命令,其中
尝试生成布尔相等性和可判定性证明 平常的平等。如果识别涉及其他一些归纳类型, 必须首先确定它们的平等性。
因此可以自动生成T_beq : T -> T -> bool
和T_eq_dec : forall x y : T, {x = y} + {x <> y}
。
答案 0 :(得分:7)
问题是您使用Qed
命令结束证明。这会导致您刚定义的eq_dec
函数变为不透明,从而阻止Coq简化涉及它的表达式。在这种情况下,一个简单的解决方案是使用Defined
代替:
Require Import Coq.Lists.List.
Import List.ListNotations.
Inductive T : Set := A | B | C.
Lemma eq_dec : forall a b : T, {a = b} + {a <> b}.
Proof.
destruct a, b; try (left; reflexivity); try (right; congruence).
Defined.
Definition f (xs : list T) : list T := List.remove eq_dec A xs.
Theorem foo : f [ A; B; C ] = [ B; C ].
Proof. reflexivity. Qed.
您可以查看Adam Chlipala的CPDT book以了解有关此编程风格的更多信息。
还有一种替代方法,我个人更喜欢。我们的想法是编写返回布尔值的正常相等测试,并在测试正确后证明。这有两个原因。
它允许重用标准布尔运算符来编写这些函数;以及
涉及校样的函数(如eq_dec
)可能会与Coq的还原机制发生严重交互,因为还原需要考虑校样。
您可以在Software Foundations book中详细了解此替代风格。您还可以查看mathematical components库,它可以普遍使用此样式 - 例如,定义type with decidable equality的概念。
答案 1 :(得分:5)
您还可以保持可判定等式的证明不透明,但在这种情况下,您必须使用除reflexivity
之外的其他策略来证明您的结果。
在与您的示例相同的上下文中,请尝试以下操作:
Theorem foo : f [ A; B; C ] = [ B; C ].
Proof.
unfold f; simpl; case (eq_dec A A);[intros _ | intros abs; case abs; auto].
case (eq_dec A B);[discriminate | intros _].
case (eq_dec A C);[discriminate | intros _].
reflexivity.
Qed.
当您想要更抽象地推理类型元素之间的相等性以及计算无法为您做任何事情时,了解此解决方案的存在可能非常有用。