可判定的平等如何与 List.remove 一起使用?

How does decidable equality works with List.remove?

我从 Coq 开始,发现我必须提供可判定相等性的证明才能使用 List.remove。例如

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]".

这种可判定的平等是如何运作的,我可以阅读哪些好的资料?

编辑 1

我刚刚了解了 decide equality 策略,

solves a goal of the form forall x y:R, {x=y}+{~x=y}, where R is an inductive type such that its constructors do not take proofs or functions as arguments, nor objects in dependent types.

所以eq_dec可以重写:

Lemma eq_dec : forall a b : T, {a = b} + {a <> b}.
Proof. decide equality. Defined.

编辑 2

我刚刚了解了 Scheme Equality for T 命令,

Tries to generate a Boolean equality and a proof of the decidability of the usual equality. If identi involves some other inductive types, their equality has to be defined first.

所以T_beq : T -> T -> boolT_eq_dec : forall x y : T, {x = y} + {x <> y}可以自动生成

问题是您使用了 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 以了解有关这种编程风格的更多信息。

还有一个替代方法,我个人比较喜欢。这个想法是编写 return 布尔值的正常相等性测试,并在测试正确之后证明。这很有用,原因有二。

  1. 它允许重用标准布尔运算符来编写这些函数;和

  2. 涉及证明的函数(如 eq_dec)可能与 Coq 的归约机制交互不良,因为归约需要考虑证明。

您可以在 Software Foundations book. You can also have a look at the mathematical components library, which uses this style pervasively -- for example, to define a notion of type with decidable equality.

中阅读有关此替代样式的更多信息

您也可以保持可判定相等性的证明不透明,但在这种情况下,您必须使用 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.

当您想更抽象地推理类型元素之间的相等性以及计算无法为您完成所有事情时,了解此解决方案的存在可能非常有用。