Coq:将信息保存在匹配声明中

时间:2014-12-05 12:48:28

标签: recursion coq

我正在构建一个在列表match上执行l的递归函数。在cons分支中,我需要使用l = cons a l'的信息来证明递归函数终止。但是,当我使用match l时,信息会丢失。

如何使用match来保存信息?

以下是函数(dropdrop_lemma_le在最后给出,以便于阅读):

Fixpoint picksome (l:list nat) (H : Acc lt (length l)) {struct H}: list nat.
    refine (
        match l with
            nil => nil
          | cons a l' => cons a (picksome (drop a l') _)
        end
      ).

    apply H.
    assert (l = cons a l') by admit.  (* here is where I need the information *)
    rewrite H0.
    simpl.
    apply le_lt_n_Sm.
    apply drop_lemma_le.
Defined. (* Can't end definition here because of the 'admit'. *)

我实际上能够通过refine定义整个函数,如下所示,但它实际上并不可读。做Print picksome.揭示了Coq如何处理这个问题,但是对于嵌套函数等来说它也很长并且不可读。

必须有一种更易读的方式来写它,对吧?

Fixpoint picksome (l:list nat) (H : Acc lt (length l)) {struct H}: list nat.
Proof.
  refine ( _ ).
  remember l as L.
  destruct l as [| a l'].
  apply nil.
  apply (cons a).
  apply (picksome (drop a l')).
  apply H.
  rewrite HeqL.
  simpl.
  apply le_lt_n_Sm.
  apply drop_lemma_le.
Defined.

我的第一次尝试是尝试这样的事情

Definition list_cons_dec {T} (l:list T) :
  {exists a l', l=a::l'} + {~ exists a l', l=a::l'}.
  remember l as L.
  destruct l as [| a l'].
  - right; subst L; intros [a [A B]]; inversion B.
  - left; exists a, l'; apply HeqL.
Defined.

Fixpoint picksome (l:list nat) (H : Acc lt (length l)) {struct H}: list nat.
Proof.
  refine (
      match list_cons_dec l with
        | right Hdec => nil
        | left Hdec => cons _ (picksome (drop _ _) _)
      end
    ).
  destruct l.
  inversion Hdec.  (* fails *)

我无法了解al'的实际lError: Inversion would require case analysis on sort Set which is not allowed for inductive definition ex. 。 Coq抱怨道:

drop

这样做的正确(可读)方法是什么?


以下是drop_lemma_leFixpoint drop {T} n (l:list T) := match n with | O => l | S n' => match l with | nil => nil | cons _ l' => drop n' l' end end. Lemma drop_lemma_le : forall {T} n (l:list T), length (drop n l) <= (length l). Proof. intros; generalize n; induction l; intros; destruct n0; try reflexivity. apply le_S; apply IHl. Defined. 的定义。

{{1}}

1 个答案:

答案 0 :(得分:7)

要记住你在模式匹配的列表中看起来像什么,你需要简单地改变匹配的返回类型。

Fixpoint picksome (l:list nat) (H : Acc lt (length l)) {struct H}: list nat.
    refine (
        (match l as m return l = m -> list nat with
            nil       => fun Hyp => nil
          | cons a l' => fun Hyp => cons a (picksome (drop a l') _)
        end) (eq_refl l)
      ).

match l as m return l = m -> list nat所说的是,您正在l上执行模式匹配,您将调用匹配的表单m,并且证明{{1}等于l,你将构建一个nat列表。

现在,m块的类型会略有不同:它不是仅提供match,而是提供list nat类型的函数。幸运的是,l = l -> list nat提供了eq_refl l等同于自己的证明,因此我们可以将匹配应用于该值并返回我们的初始l

看看比赛的分支,我们可以看到:

  • list nat案例中,您可以忽略您不需要的额外假设。

  • nil案例中,它为您提供了非常需要的假设,您可以履行证明义务:

    cons

    定义。