为什么这种重写在依赖类型的上下文中失败

时间:2016-04-19 08:10:02

标签: coq

我试图依赖依赖类型,但我不断遇到如下问题。在这个例子中,我定义了一个数组的抽象,这样每个访问都被保护在使用依赖类型的数组中。

我使用的是Coq 8.5,但我不认为这个例子很重要。我还使用了Software Foundations教程中的SfLibLibTactics。对于后者,我发现了一个与Coq 8.5一起使用的方法。

Add LoadPath "/home/bryan/Projects/Coq/sf8.5".
Require Import SfLib.      (* In the download from https://www.cis.upenn.edu/~bcpierce/sf/current/index.html *)
Require Import LibTactics. (* https://github.com/DDCSF/iron/blob/master/done/Iron/Tactics/LibTactics.v *)

Require Import Omega.

Module Array.

接下来是数组的归纳和抽象定义。

  Inductive array {E: Type} (sz: nat) : Type :=
  | construct_array : forall f : nat -> option E, (forall i, i >= sz <-> f i = None) -> array sz
  .

接下来有几个lemmas,毫无疑问在标准库中可用,但除了第二个之外我无法找到它们,但那只是在Classical逻辑部分。

  Lemma transpose: forall f g : Prop, (f -> g) -> (~ g -> ~ f).
  Proof.
    auto.
  Qed.

  Lemma not_ex_all_not :
   forall U (P:U -> Prop), ~ (exists n, P n) -> forall n:U, ~ P n.
  Proof. (* Intuitionistic *) 
    unfold not. intros U P notex n abs.
    apply notex. 
    exists n; trivial. 
  Qed.

以下引理表征了数组的定义。证明感觉就像是一种力量,所以如果你有任何简化的建议,那么无论如何。

  Lemma inside_array: forall E (f: nat -> option E) sz
  ,   (forall i, i >= sz <-> f i = None) 
  <-> (forall i, i < sz <-> exists e, f i = Some e)
  .   
  Proof.  
    introv. split; split.
    introv Hi. remember (f i) as fi. destruct fi.
      exists e. reflexivity.
      symmetry in Heqfi. rewrite <- H in Heqfi. exfalso. omega.
    introv Hex. inversion Hex as [e He]; clear Hex.
    specialize (H i). rewrite He in H. inversion H; clear H.
    apply transpose in H0. SearchAbout ge. apply not_ge in H0. assumption.
    intro Hcontra. inversion Hcontra.
    intro Hi. specialize (H i). inversion H.
    apply transpose in H1. assert (forall e, ~ f i = Some e). apply not_ex_all_not. assumption.
    destruct (f i). specialize (H2 e). exfalso. auto. reflexivity.
    omega.
    intros Hi. specialize (H i). inversion H. apply transpose in H0. omega. rewrite Hi.
    intro Hcontra. inversion Hcontra as [e Hcontra']. inversion Hcontra'.
  Qed.

如果索引在范围

中,则查找数组中的元素
  Definition lu_array {E: Type} {sz: nat} (a: @array E sz) (i: nat) (C: i < sz) : E.
  Proof.  
    intros.
    inversion a.
    remember (f i) as elem.
    destruct (elem).
      apply e. symmetry in Heqelem. rewrite <- H in Heqelem.
      exfalso. omega.
  Defined.

通过在前面放置新元素

来调整阵列大小
 Definition inc_l_array {E: Type} {sz: nat} (a: @array E sz) (inc: nat) (d: E) : @array E (inc + sz).
 Proof.
    destruct a as [f Hi].
    apply construct_array
      with (fun j => if lt_dec j inc then Some d else if lt_dec j (inc + sz) then f (j - inc) else None).
    introv. split; destruct (lt_dec i inc); simpl.
    Case "i < inc ->". introv Hi'. exfalso. omega.
    Case "i >= inc ->". introv Hi'. destruct (lt_dec i (inc + sz)).
      SCase "i < (inc + sz)". exfalso. omega.
      SCase "i >= (inc + sz)". reflexivity.
    Case "i < inc <-". introv Hcontra. inversion Hcontra.
    Case "i >= inc <-". destruct (lt_dec i (inc + sz)).
      SCase "i < (inc + sz)". rewrite <- Hi. omega.
      SCase "i >= (inc + sz)". introv Htriv. omega.
  Defined.

接下来是有问题的引理,它指定了调整大小应该做什么。大多数证据都会失败,但我会被标记为重写。

  Lemma inc_l_array_spec
  :   forall E sz (a: @array E sz) (inc: nat) (d: E) (a': @array E (inc + sz))
  ,   inc_l_array a inc d = a'
      ->  forall i (Ci' : i < inc + sz)
      ,   (   i < inc -> lu_array a' i Ci' = d)
      /\  (   inc <= i < inc + sz
          ->  exists (Ci: i-inc < sz), lu_array a' i Ci' = lu_array a (i-inc) Ci
          )
  .
  Proof.
    introv Heq. introv. subst a'. destruct a as [f Hf]. split; introv Hin.
    Case "i < inc". simpl.
      unfold inc_l_array, lu_array.
      destruct (lt_dec i inc).
      SCase "i < inc". reflexivity.
      SCase "i >= inc". contradiction.  
    Case "inc <= i < inc+sz".
      assert (Ci: i-inc < sz) by omega. exists Ci.
      unfold inc_l_array, lu_array. 
      destruct (lt_dec i inc).
      SCase "i < inc". exfalso. omega. 
      SCase "i >= inc". destruct (lt_dec i (inc+sz)).
        SSCase "i < inc + sz".
          assert (Hf': forall i, i < sz <-> exists e, f i = Some e).
          apply inside_array. assumption.
          specialize (Hf' (i-inc)). inversion Hf'. remember Ci as Ci''. clear HeqCi''. apply H in Ci.
          inversion Ci as [e He].
          rewrite He. (* <---- This rewrite fails *)

        SSCase "i >= inc + sz".
          exfalso. omega. 
  Qed.

End Array.

我已经尝试过以其他方式解决这个问题,但它始终会遇到这个问题。错误消息如下所示:

Error: Abstracting over the term "f (i - inc)" leads to a term
fun o : option E => (... very long term ...) which is ill-typed.
Reason is: Illegal application: 
The term "@RelationClasses.symmetry" of type
 "forall (A : Type) (R : Relation_Definitions.relation A),
  RelationClasses.Symmetric R -> forall x y : A, R x y -> R y x"
cannot be applied to the terms
 "Prop" : "Type"
 "iff" : "Prop -> Prop -> Prop"
 "RelationClasses.iff_Symmetric" : "RelationClasses.Symmetric iff"
 "i - inc >= sz" : "Prop"
 "o = None" : "Prop"
 "Hf (i - inc)" : "i - inc >= sz <-> f (i - inc) = None"
The 6th term has type "i - inc >= sz <-> f (i - inc) = None"
which should be coercible to "i - inc >= sz <-> o = None".

o = None看起来像罪魁祸首,因为它似乎涵盖了我此刻未处理的案件。但老实说,我不明白发生了什么。在第六学期提到f (i - inc)也让我感到担忧,因为我打算将其改写掉。

上述方法将依靠证据不相关来连接类型相关的警卫。但是我不明白如何在上述情况下调用这个公理。

我的具体问题是:为什么重写失败?我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

我仔细研究了你在做什么,这里有一些评论:

  • 你依赖于透明的样张,这通常是一点点 潘多拉盒子,因为你的一些证明条款将是“不透明的”,并且在 将军会让事情变得有点困难。
  • 你可以尝试分开更多的证据和“数据”。
  • 您还可以尝试使用更多“计算”定义。那 是,为什么不将数组作为实际列表呢?

请参阅下文,我的代码需要5分钟,希望有所帮助。

From mathcomp
Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice fintype.

Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.

Section Array.

Variable E : Type.
Implicit Types N   : nat.

Definition i_fun := nat -> option E.
Implicit Types arr : i_fun.
Identity Coercion i_fun_c : i_fun >-> Funclass.

(* A maybe better approach would be to work with reflect predicates *)
(* Definition up_axiom arr N := forall i, *)
(*     reflect (arr i = None) (N <= i). *)

Definition up_axiom arr N := forall i,
    (arr i = None) <-> (N <= i).

Definition down_axiom arr N := forall i,
    (exists e, arr i = Some e) <-> (i < N).

Definition array N := { arr | up_axiom arr N }.

Coercion arr_fun N (arr : array N) := tag arr.

(* Sadly we can't fully reflect this *)
Lemma inside_array arr N : up_axiom arr N <-> down_axiom arr N.
Proof.
split=> ax i; split.
+ by case=> [e he]; rewrite ltnNge; apply/negP/ax; rewrite he.
+ move=> hi; case Ha: (arr i) => [w|]; first by exists w.
  by move/ax: Ha; rewrite leqNgt hi.
+ have := ax i; case: (arr i) => // -[h1 h2 _].
  by rewrite leqNgt; apply/negP=> /h2 [].
+ have := ax i; case: (arr i) => // e [h1 h2].
  have H: i < N; first by apply: h1; exists e.
  by rewrite leqNgt H.
Qed.

(* This being transparent was not very useful... *)
Definition optdef T d (e : option T) : T :=
  match e with
  | Some x => x
  | None => d
  end.

Definition get_array N d arr (i : nat) : E :=
  optdef d (arr i).

Definition inc_array N arr (inc : nat) (d: E) : i_fun :=
  fun i =>
  if i < N       then arr i else
  if i < N + inc then Some d else
  None.

Lemma inc_arrayP N (arr : array N) inc d :
  up_axiom (inc_array N arr (N+inc) d) (N+inc).
Proof.
case: arr => a_f a_ax i; have [h1 h2] := a_ax i.
rewrite /inc_array /arr_fun; case: ifP => hi /=.
+ split; [move/h1; rewrite leqNgt hi //|].
  move=> hil; rewrite (leq_trans (leq_addr inc _)) // in h2.
  exact: h2.