使用模式匹配表达式的destruct与'convoy pattern'

时间:2017-11-17 07:11:48

标签: coq

出于这个问题的目的,假设我有:

Parameter eq_bool : forall (A:Type), A -> A -> bool.

Arguments eq_bool {A} _ _.

Axiom eq_bool_correct : forall (A:Type) (x y:A),
    eq_bool x y = true -> x = y.

Axiom eq_bool_correct' : forall (A:Type) (x y:A),
     x = y -> eq_bool x y = true.

我有一个函数,只要x y:ASome,就会给x = y两个值x = y None证明eq_bool x y。此函数通过Definition test (A:Type) (x y:A) : option (x = y) := match eq_bool x y as b return eq_bool x y = b -> option (x = y) with | true => fun p => Some (eq_bool_correct A x y p) | false => fun _ => None end (eq_refl (eq_bool x y)). 上的模式匹配来实现,以测试相等性,并使用convoy模式作为一种技巧,在代码中访问对应于匹配分支的相等证明:

Theorem basic: forall (A:Type) (x y:A),
    x = y -> test A x y <> None.
Proof.
    intros A x y H. rewrite H. unfold test.

A : Type
x, y : A
H : x = y
============================
(if eq_bool y y as b return (eq_bool y y = b -> option (y = y))
 then fun p : eq_bool y y = true => Some (eq_bool_correct A y y p)
 else fun _ : eq_bool y y = false => None) eq_refl <> None

我现在试图证明这个函数的简单结果:

destruct

此时我觉得我必须在eq_bool y y上使用destruct (eq_bool y y). Error: Abstracting over the term "b" leads to a term fun b0 : bool => (if b0 as b1 return (b0 = b1 -> option (y = y)) then fun p : b0 = true => Some (eq_bool_correct A y y p) else fun _ : b0 = false => None) eq_refl <> None which is ill-typed. Reason is: Illegal application: The term "eq_bool_correct" of type "forall (A : Type) (x y : A), eq_bool x y = true -> x = y" cannot be applied to the terms "A" : "Type" "y" : "A" "y" : "A" "p" : "b0 = true" The 4th term has type "b0 = true" which should be coercible to "eq_bool y y = true". (可能保持等式):

destruct

我知道我必须阅读CPDT(特别是在护送模式上),但我对软件基础书(适合初学者)有更好的学习经验:就我目前的技能水平而言,除了{之外我什么都想不到{1}}并且希望有人可以建议一种方法来完成这个证明。

1 个答案:

答案 0 :(得分:5)

这是一种典型的情况,粗心抽象使得术语输入错误。一般情况下,您希望使用稍微不同的原则来避免这些问题,sumboolreflect上的匹配可能会为您提供更好的结果。

在这种特殊情况下,为了让事情顺利进行,你首先需要稍微概括一下目标(因此它不依赖于eq_refl,这在匹配时会出现问题,因为它的输入规则也是如此严格)然后选择适当的子项。我使用ssreflect模式语言,因为它更方便:

(* Do From Coq Require Import ssreflect. *)
Theorem basic (A : Type) (x y : A) (p : x = y) : test x y <> None.
Proof.
rewrite p /test; move: eq_refl; case: {2 3}(eq_dec y y) => //.
by rewrite eq_dec_correct'.
Qed.

实际上,我们需要选择匹配匹配中的eq_dec的出现以及相等证明的右侧。您可以采取上述证据,或者您可以将上述内容视为构建并证明更为一般的引理:

Theorem basic0 (A : Type) (x : A) b (p : eq_dec x x = b) :
  match b as b1 return eq_dec x x = b1 -> option (x = x) with
  | true  => fun p => Some (eq_dec_correct p)
  | false => fun _ => None
  end p <> None.
Proof. by case: b p; rewrite ?eq_dec_correct'. Qed.

Theorem basic1 (A : Type) (x y : A) (p : x = y) : test x y <> None.
Proof. by rewrite p; apply: basic0. Qed.

请注意,在这里,通过仔细选择我们的参数,我们避免了必须使用模式选择执行技巧。关键步骤是“匹配”匹配中的布尔值与“convoy”参数中存在的eq_dec见证,因此我们仍然可以正确键入对eq_dec_correct的调用。最后一点有趣的是,我们还必须将eq_dec x x = eq_dec x x转换为eq_dec x x = b,因此我们需要对等式证明进行抽象。

但正如我之前所说,你可能想要定义一个更普遍的引理。 [为什么不使用eqtype中已存在的一些引理?]