出于这个问题的目的,假设我有:
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:A
和Some
,就会给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}}并且希望有人可以建议一种方法来完成这个证明。
答案 0 :(得分:5)
这是一种典型的情况,粗心抽象使得术语输入错误。一般情况下,您希望使用稍微不同的原则来避免这些问题,sumbool
或reflect
上的匹配可能会为您提供更好的结果。
在这种特殊情况下,为了让事情顺利进行,你首先需要稍微概括一下目标(因此它不依赖于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
中已存在的一些引理?]