使用Program
时,匹配语句会被重写为"证明传递"样式。这证明了分支中可用的匹配 - 这可能是关键的。
然而,它似乎也使案例分析更加困难。例如:
Require Import ZArith.
Open Scope Z_scope.
Program Definition test (x:Z) : option (x <= 100) :=
match Z_le_gt_dec x 100 with
| left bound => Some _
| right bound => None
end.
Lemma test_gt_100 : forall x:Z, x > 100 -> test x = None.
Proof.
intros x bound.
unfold test.
此时,通常会destruct (Z_le_gt_dec x 100)
,然后证明就容易了。但是,重写的匹配给出了这样的背景:
x : Z
bound : x > 100
============================
match
Z_le_gt_dec x 100 as x0
return (x0 = Z_le_gt_dec x 100 -> option (x <= 100))
with
| left bound0 =>
fun Heq_anonymous : left bound0 = Z_le_gt_dec x 100 =>
Some (test_obligation_1 x bound0 Heq_anonymous)
| right bound0 => fun _ : right bound0 = Z_le_gt_dec x 100 => None
end eq_refl = None
这样,破坏失败了:
Toplevel input, characters 20-48:
Error: Abstracting over the term "s" leads to a term
"fun s : {x <= 100} + {x > 100} =>
match s as x0 return (x0 = s -> option (x <= 100)) with
| left bound =>
fun Heq_anonymous : left bound = s =>
Some (test_obligation_1 x bound Heq_anonymous)
| right bound => fun _ : right bound = s => None
end eq_refl = None" which is ill-typed.
走得更慢,只想generalize (Z_le_gt_dec x 100)
来说明原因:
Toplevel input, characters 0-30:
Error: Illegal application (Type Error):
The term "test_obligation_1" of type
"forall x : Z,
let filtered_var := Z_le_gt_dec x 100 in
forall bound : x <= 100, left bound = filtered_var -> x <= 100"
cannot be applied to the terms
"x" : "Z"
"bound0" : "x <= 100"
"Heq_anonymous" : "left bound0 = s"
The 3rd term has type "left bound0 = s" which should be coercible to
"left bound0 = Z_le_gt_dec x 100".
虽然这是有道理的,但我不知道如何处理它。
(如果有帮助的话,我已将其放在collacoq中。不要忘记先执行注释行,然后等到所有库都加载后再导入ZArith。)
答案 0 :(得分:2)
这里的问题是你依赖于一个特定的平等术语,抽象它应该允许你继续。 (通常的做法是说明独立于证据的引理)。
这是你的例子,使用ssreflect的重写。抱歉,我无法指示Coq的人选择合适的模式。
Comments "pkgs: coq-reals".
From mathcomp Require Import ssreflect.
Require Import Coq.ZArith.ZArith.
Open Scope Z_scope.
Program Definition test (x:Z) : option (x <= 100) :=
match Z_le_gt_dec x 100 with
| left bound => Some _
| right bound => None
end.
Lemma test_gt_100 : forall x:Z, x > 100 -> test x = None.
Proof.
intros x hb; unfold test.
assert (Z_le_gt_dec x 100 = right hb) as Hz. admit.
move: eq_refl; rewrite {1 3}Hz.
done.
[也在https://x80.org/collacoq/xareboqura.coq]
最好的问候,E。
编辑:更详细一点:在开始时,匹配的参数是eq_refl : forall x, x = x
,这是正常的,因为匹配中的函数需要类型为Z.le .... = Z.le ....
的术语。但是,在执行重写时,匹配注释中的类型将变为Z_le ... = right ...
形式,但如果参数仍为eq_refl
,则会导致类型错误的术语,因为eq_refl
可以永远不要输入Z.le ... = right ...
!
因此,我们修改了我们的目标,以便相等的证明不一定必须是eq_refl
,然后我们重写。
为什么首先使用eq_refl
进行了证明?这通常是为了在存在相等证明的情况下具有良好的减少行为。
为程序添加与证据无关的支持会很有趣。 (我忽略了,如果已经有一些)。