Lvc.Infra.MoreList

Require Import OrderedTypeEx Util List Get Computable DecSolve AllInRel.

Set Implicit Arguments.

Lemmas and tactics for lists


Lemma app_nil_eq X (L:list X) xl
  : L = xl ++ Lxl = nil.
intros. rewrite <- (app_nil_l L ) in H at 1.
eauto using app_inv_tail.
Qed.

Lemma cons_app X (x:X) xl
  : x::xl = (x::nil)++xl.
eauto.
Qed.

Fixpoint tabulate X (x:X) n : list X :=
  match n with
    | 0 ⇒ nil
    | S nx::tabulate x n
  end.

Section ParametricZip.
  Variables X Y Z : Type.
  Hypothesis f : XYZ : Type.

  Fixpoint zip (L:list X) (:list Y) : list Z :=
    match L, with
      | x::L, y::f x y::zip L
      | _, _nil
    end.

  Lemma zip_get L n (x:X) (y:Y)
  : get L n xget n yget (zip L ) n (f x y).
  Proof.
    intros. general induction n; inv H; inv H0; simpl; eauto using get.
  Qed.

  Lemma get_zip L n (z:Z)
  : get (zip L ) n z
    → { x : X & {y : Y | get L n x get n y f x y = z } } .
  Proof.
    intros. general induction L; destruct ; isabsurd.
    simpl in H. destruct n.
    - eexists a; eexists y. inv H; eauto using get.
    - edestruct IHL as [ [ ?]]; dcr; try inv H; eauto 20 using get.
  Qed.

  Lemma zip_tl L
    : tl (zip L ) = zip (tl L) (tl ).
  Proof.
    general induction L; destruct ; simpl; eauto.
    destruct L; simpl; eauto.
  Qed.

End ParametricZip.

Arguments zip [X] [Y] [Z] f L .
Arguments zip_get [X] [Y] [Z] f [L] [] [n] [x] [y] _ _.

Lemma map_zip X Y Z (f: XYZ) W (g: ZW) L
: map g (zip f L ) = zip (fun x yg (f x y)) L .
Proof.
  general induction L; destruct ; simpl; eauto using f_equal.
Qed.

Lemma zip_map_l X Y Z (f: XYZ) W (g: WX) L
: zip f (map g L) = zip (fun x yf (g x) y) L .
Proof.
  general induction L; destruct ; simpl; eauto using f_equal.
Qed.

Lemma zip_map_r X Y Z (f: XYZ) W (g: WY) L
: zip f L (map g ) = zip (fun x yf x (g y)) L .
Proof.
  general induction L; destruct ; simpl; eauto using f_equal.
Qed.

Lemma zip_ext X Y Z (f :XYZ) L
 : ( x y, f x y = x y) → zip f L = zip L .
Proof.
  general induction L; destruct ; simpl; eauto.
  f_equal; eauto.
Qed.

Lemma zip_length X Y Z (f:XYZ) L
      : length (zip f L ) = min (length L) (length ).
Proof.
  general induction L; destruct ; simpl; eauto.
Qed.

Lemma zip_length2 {X Y Z} {f:XYZ} DL ZL
: length DL = length ZL
  → length (zip f DL ZL) = length DL.
Proof.
  intros. rewrite zip_length. rewrite H. rewrite Min.min_idempotent. eauto.
Qed.

Section ParametricMapIndex.
  Variables X Y : Type.
  Hypothesis f : natXY : Type.

  Fixpoint mapi_impl (n:nat) (L:list X) : list Y :=
    match L with
      | x::Lf n x::mapi_impl (S n) L
      | _nil
    end.

  Definition mapi := mapi_impl 0.

  Lemma mapi_get_impl L i y n
  : getT (mapi_impl i L) n y{ x : X & (getT L n x × (f (n+i) x = y))%type }.
  Proof.
    intros. general induction X0; simpl in *;
            destruct L; simpl in *; inv Heql;
          try now (econstructor; eauto using getT).
    edestruct IHX0; dcr; eauto using getT.
    eexists x1; split; eauto using getT.
    rewrite <- b. f_equal; omega.
  Qed.

  Lemma mapi_get L n y
  : get (mapi L) n y{ x : X | get L n x f n x = y }.
  Proof.
    intros. eapply get_getT in H. eapply mapi_get_impl in H; dcr.
    orewrite (n+0 = n) in b.
    eexists; eauto using getT_get.
  Qed.

  Lemma mapi_length L {n}
  : length (mapi_impl n L) = length L.
  Proof.
    general induction L; simpl; eauto using f_equal.
  Qed.

End ParametricMapIndex.

Arguments mapi [X] [Y] f L.
Arguments mapi_impl [X] [Y] f n L.

Lemma map_impl_mapi X Y Z L {n} (f:natXY) (g:YZ)
 : List.map g (mapi_impl f n L) = mapi_impl (fun n xg (f n x)) n L.
Proof.
  general induction L; simpl; eauto using f_equal.
Qed.

Lemma map_mapi X Y Z L (f:natXY) (g:YZ)
 : List.map g (mapi f L) = mapi (fun n xg (f n x)) L.
Proof.
  unfold mapi. eapply map_impl_mapi.
Qed.

Lemma mapi_map_ext X Y L (f:natXY) (g:XY) n
 : ( x n, g x = f n x)
   → List.map g L = mapi_impl f n L.
Proof.
  intros. general induction L; unfold mapi; simpl; eauto.
  f_equal; eauto.
Qed.

Lemma map_ext_get_eq X Y L (f:XY) (g:XY)
 : ( x n, get L n xg x = f x)
   → List.map g L = List.map f L.
Proof.
  intros. general induction L; unfold mapi; simpl; eauto.
  f_equal; eauto using get.
Qed.

Lemma map_ext_get X Y (R:YYProp) L (f:XY) (g:XY)
 : ( x n, get L n xR (g x) (f x))
   → PIR2 R (List.map g L) (List.map f L).
Proof.
  intros. general induction L; simpl. econstructor.
  econstructor; eauto using get.
Qed.

Ltac list_eqs :=
  match goal with
    | [ : ?x :: ?L = ? ++ ?L |- _ ] ⇒
      rewrite cons_app in ; eapply app_inv_tail in
    | [ H : ?L = ? ++ ?L |- _ ] ⇒
      let A := fresh "A" in
        eapply app_nil_eq in H
    | _fail "no matching assumptions"
  end.

Ltac inv_map H :=
  match type of H with
    | get (List.map ?f ?L) ?n ?x
      match goal with
        | [ : get ?L ?n ?y |- _ ] ⇒
          let EQ := fresh "EQ" in pose proof (map_get f H) as EQ; invc EQ
        | _let X := fresh "X" in let EQ := fresh "EQ" in
              pose proof (map_get_4 _ f H) as X; destruct X as [? [? EQ]]; invc EQ
      end
  end.

Lemma list_eq_get {X:Type} (L :list X) eqA n x
  : list_eq eqA L get L n x , get n eqA x .
Proof.
  intros. general induction H.
  inv H0.
  inv H1. eauto using get.
  edestruct IHlist_eq; eauto. firstorder using get.
Qed.

Instance list_R_dec A (R:AAProp)
         `{ a b, Computable (R a b)} (L:list A) (:list A) :
  Computable ( n a b, get L n aget n bR a b).
Proof.
  general induction L; destruct .
  + left; isabsurd.
  + left; isabsurd.
  + left; isabsurd.
  + decide (R a a0). edestruct IHL; eauto.
    left. intros. inv H0; inv H1; eauto.
    right. intro. eapply n; intros. eapply H0; eauto using get.
    right. intro. eapply n. eauto using get.
Qed.

Instance list_eq_computable X (R:XXProp) `{ x y, Computable (R x y)}
: (L :list X), Computable (list_eq R L ).
Proof.
  intros. decide (length L = length ).
  - general induction L; destruct ; isabsurd; try dec_solve.
    decide (R a x); try dec_solve.
    edestruct IHL with (:=); eauto; try dec_solve.
  - right; intro. exploit list_eq_length; eauto.
Qed.

Ltac inv_mapi H :=
  match type of H with
    | get (mapi ?f ?L) ?n ?x
      match goal with
        | [ : get ?L ?n ?y |- _ ] ⇒
          let EQ := fresh "EQ" in pose proof (mapi_get f H) as EQ; invc EQ
        | _let X := fresh "X" in let EQ := fresh "EQ" in
              pose proof (mapi_get f _ H) as X; destruct X as [? [? EQ]]; invc EQ;
             clear_trivial_eqs
      end
  end.

Instance list_get_computable X (Y:list X) (R:XProp) `{ (x:X), Computable (R x)}
: Computable ( n y, get Y n yR y).
Proof.
  hnf. general induction Y.
  - left; isabsurd.
  - decide (R a).
    + edestruct IHY; eauto.
      × left; intros. inv H0; eauto using get.
      × right; intros; eauto using get.
    + right; eauto using get.
Defined.