如何处理返回类型为a=b→c的match项(护航模式)的Coq证明
Coq护航模式下的证明推进问题
我在Coq开发中推进到以下证明目标后无法继续:
A: Type a: list (list A) b: list A i,j: nat Hi: i < length a Hj: j < length (nth i a []) -------------------------------------------- nth_error (nth i a []) j = Some (match nth2 i j as e return (nth2 i j = e -> A) with | Some a0 => fun _ : nth2 i j = Some a0 => a0 | None => fun H : nth2 i j = None => False_rect A (nth2_not_None Hi Hj H) end eq_refl)
我无法将nth2 i j改写为Some x(尽管已证明它不可能是None)。想请教:当使用返回类型为a=b -> c的护航模式时,该如何推进这个证明?注意:我不需要改用其他没有这个问题的nth2定义方案。
完整代码
Require Import List. Import ListNotations. Require Import Fin. Section Example. Variable (A:Type). Variable (a:list (list A)) (b: list A). Definition indices := { '(i, j):(nat * nat) | i < length a /\ j < length (nth i a [])}. Definition lookup_spec (f:indices -> A) := forall ij, let '(i,j) := proj1_sig ij in nth_error (nth i a []) j = Some (f ij). Definition nth2 i j : option A := match nth_error a i with Some ai => nth_error ai j | None => None end. Lemma nth2_not_None {i j} (Hi: i < length a) (Hj: j < length (nth i a [])): nth2 i j <> None. unfold nth2. enough (exists (d:A), True) as [d _] by now rewrite (nth_error_nth' _ [] Hi), (nth_error_nth' _ d Hj). destruct (nth i a []) as [| x l]. now exfalso. now exists x. Defined. Definition lookup (ij : indices): A := let '(exist _ (i, j) (conj Hi Hj)) := ij in match nth2 i j as e return nth2 i j = e -> A with | Some a => fun _ => a | None => fun H => False_rect _ (nth2_not_None Hi Hj H) end eq_refl. Lemma lookup_ok: lookup_spec lookup. intros [[i j] [Hi Hj]]. unfold proj1_sig, lookup. (* 在此处卡壳 *)
解决方案
要处理这种护航模式的证明,核心思路是对nth2 i j进行分情况讨论,利用已有的Hi和Hj排除None的分支:
- 首先,对
nth2 i j执行分情况解构并保留等式关系:destruct (nth2 i j) eqn:E。 - 对于
None分支,结合nth2_not_None Hi Hj E可直接导出矛盾,用contradiction消除该分支。 - 对于
Some x分支,此时目标中的match表达式会被化简为x,再结合nth2的定义与Hi,将左边的nth_error (nth i a []) j与Some x关联,完成证明。
具体补充的证明步骤如下:
Lemma lookup_ok: lookup_spec lookup. intros [[i j] [Hi Hj]]. unfold proj1_sig, lookup. (* 对nth2的结果分情况,记录等式 *) destruct (nth2 i j) eqn:E. - (* 分支:nth2 i j = Some a0 *) simpl. (* 此时match会被化简为a0 *) unfold nth2 in E. (* 利用Hi得到nth_error a i = Some (nth i a []) *) rewrite (nth_error_nth' _ [] Hi) in E. simpl in E. (* 此时E变为nth_error (nth i a []) j = Some a0,正好匹配目标 *) rewrite E. reflexivity. - (* 分支:nth2 i j = None *) (* 调用nth2_not_None得到矛盾 *) specialize (nth2_not_None Hi Hj E). contradiction. Qed.
关键在于通过destruct ... eqn:E保留nth2 i j的结果与原表达式的等式关系,这样在Some分支中可以直接用该等式改写目标,而None分支则通过已有的引理直接排除。
内容的提问来源于stack exchange,提问作者larsr
相关产品推荐
相关产品推荐

