Coq中`destruct`和`case_eq`战术有什么区别?

时间:2017-09-27 05:49:32

标签: coq

我理解destruct因为它将归纳定义分解为其构造函数。我最近看到case_eq,我无法理解它的作用有何不同?

1 subgoals
n : nat
k : nat
m : M.t nat
H : match M.find (elt:=nat) n m with
    | Some _ => true
    | None => false
    end = true
______________________________________(1/1)
cc n (M.add k k m) = true

在上面的上下文中,如果我破坏M.find n m,它会将H分为true和false,而case_eq (M.find n m)将H保持原样并添加单独的命题M.find (elt:=nat) n m = Some v,我可以重写它以获得相同的效果如破坏。

有人可以解释一下这两种策略之间的区别以及应该使用哪种策略?

1 个答案:

答案 0 :(得分:13)

destructcase_eq家庭中的第一个基本策略称为case。这种策略只能修改结论。当您键入case A并且A的类型T具有归纳类型时,系统会通过所有类型构造函数的实例替换目标结论中的A T,如果需要,为这些构造函数的参数添加通用量化。这会创建与T类型中的构造函数一样多的目标。公式A从目标中消失,如果假设中有A的任何信息,则此信息与在结论中替换它的所有新构造函数之间的链接将丢失。尽管如此,case是一种重要的原始策略。

在结论中忽略假设中信息与A实例之间的链接是一个很大的问题,因此开发人员提出了两个解决方案:case_eqdestruct。< / p>

个人而言,在撰写Coq&#39; Art书时,我建议我们在case之上编写一个简单的策略,在A和各种构造函数实例之间保持链接。平等。这就是现在称为case_eq的策略。它与case做同样的事情,但在目标中增加了一个额外的含义,其中暗示的前提是形式A = ...的相等性,其中...是每个构造函数的实例

大约在同一时间,提出了destruct战术。 destruct不是将替换的影响限制在目标的结论中,而是用类型为A的构造函数的实例替换假设中出现的T的所有实例。从某种意义上说,这是更清晰,因为它避免依赖额外的平等概念,但它仍然是不完整的,因为表达式A可能是复合表达式f B,如果出现B在假设中但不是f B AB之间的链接仍将丢失。

<强>插图

Definition my_pred (n : nat) := match n with 0 => 0 | S p => p end.

Lemma example n :  n <= 1 -> my_pred n <= 0.
Proof.
case_eq (my_pred n).

给出了两个目标

------------------
n <= 1 -> my_pred n = 0 -> 0 <= 0

------------------
forall p, my_pred n = S p -> n <= 1 -> S p <= 0

额外的平等在这里非常有用。

this question中,我建议开发人员在case_eq (a == b)类型为(a == b)时使用bool,因为此类型是归纳的,而且信息量不大(构造函数没有参数)。但是当(a == b)具有类型{a = b}+{a <> b}string_dec函数的情况)时,构造函数的参数是有趣属性的证明,并且构造函数的参数的额外通用量化是足以提供相关信息,在这种情况下,a = b代表第一个目标,a <> b代表第二个目标。