如何破坏/概括程序的重写匹配语句

时间:2016-05-06 16:26:56

标签: coq

使用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。)

1 个答案:

答案 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进行了证明?这通常是为了在存在相等证明的情况下具有良好的减少行为。

为程序添加与证据无关的支持会很有趣。 (我忽略了,如果已经有一些)。