MathClasses.implementations.ne_list

This module should be Required but not Imported (except for the notations submodule).

Require Import
  Unicode.Utf8 Coq.Lists.List Setoid Morphisms Permutation.

Instance: A, Proper (@Permutation A ==> eq) (@length A).
Proof Permutation_length.

Existing Instance Permutation_map_aux_Proper.

Section contents.
  Context {T: Type}.

  Inductive L: Type := one: T L | cons: T L L.

  Fixpoint app (a b: L) {struct a}: L :=
    match a with
    | one xcons x b
    | cons x ycons x (app y b)
    end.

  Fixpoint foldr {R} (o: T R) (f: T R R) (a: L): R :=
    match a with
    | one xo x
    | cons x yf x (foldr o f y)
    end.

  Fixpoint foldr1 (f: T T T) (a: L): T :=
    match a with
    | one xx
    | cons x yf x (foldr1 f y)
    end.

  Definition head (l: L): T := match l with one xx | cons x _x end.

  Fixpoint to_list (l: L): list T :=
    match l with
    | one xx :: nil
    | cons x xsx :: to_list xs
    end.

  Global Coercion to_list: L >-> list.

  Fixpoint from_list (x: T) (xs: list T): L :=
    match xs with
    | nilone x
    | List.cons h tcons x (from_list h t)
    end.

  Definition tail (l: L): list T := match l with one _nil | cons _ xto_list x end.

  Lemma decomp_eq (l: L): l = from_list (head l) (tail l).
  Proof with auto.
    induction l...
    destruct l...
    simpl in ×.
    rewrite IHl...
  Qed.

  Definition last: L T := foldr1 (fun x yy).

  Fixpoint replicate_Sn (x: T) (n: nat): L :=
    match n with
    | 0 ⇒ one x
    | S n'cons x (replicate_Sn x n')
    end.

  Fixpoint take (n: nat) (l: L): L :=
    match l, n with
    | cons x xs, S n'take n' xs
    | _, _one (head l)
    end.

  Lemma two_level_rect (P: L Type)
    (Pone: x, P (one x))
    (Ptwo: x y, P (cons x (one y)))
    (Pmore: x y z, P z ( y', P (cons y' z)) P (cons x (cons y z))):
       l, P l.
  Proof with auto.
   cut ( l, P l × x, P (cons x l)).
    intros. apply X.
   destruct l...
   revert t.
   induction l...
   intros.
   split. apply IHl.
   intro.
   apply Pmore; intros; apply IHl.
  Qed.

  Lemma tl_length (l: L): S (length (tl l)) = length l.
  Proof. destruct l; reflexivity. Qed.

  Notation ListPermutation := (@Permutation.Permutation _).

  Definition Permutation (x y: L): Prop := ListPermutation x y.

  Global Instance: Equivalence Permutation.
  Proof with intuition.
   unfold Permutation.
   split; repeat intro...
   transitivity y...
  Qed.

  Global Instance: Proper (Permutation ==> ListPermutation) to_list.
  Proof. firstorder. Qed.

  Lemma Permutation_ne_tl_length (x y: L):
    Permutation x y length (tl x) = length (tl y).
  Proof.
   intro H.
   apply eq_add_S.
   do 2 rewrite tl_length.
   rewrite H.
   reflexivity.
  Qed.
End contents.

Arguments L : clear implicits.

Fixpoint tails {A} (l: L A): L (L A) :=
  match l with
  | one xone (one x)
  | cons x ycons l (tails y)
  end.

Lemma tails_are_shorter {A} (y x: L A):
  In x (tails y)
  length x length y.
Proof with auto.
 induction y; simpl.
  intros [[] | ?]; intuition.
 intros [[] | C]...
Qed.

Fixpoint map {A B} (f: A B) (l: L A): L B :=
  match l with
  | one xone (f x)
  | cons h tcons (f h) (map f t)
  end.

Lemma list_map {A B} (f: A B) (l: L A): to_list (map f l) = List.map f (to_list l).
Proof. induction l. reflexivity. simpl. congruence. Qed.

Global Instance: {A B} (f: A B), Proper (Permutation ==> Permutation) (map f).
Proof with auto.
 intros ????? E.
 unfold Permutation.
 do 2 rewrite list_map.
 rewrite E.
 reflexivity.
Qed.

Fixpoint inits {A} (l: L A): L (L A) :=
  match l with
  | one xone (one x)
  | cons h tcons (one h) (map (cons h) (inits t))
  end.

Module notations.
  Global Notation ne_list := L.
  Global Infix ":::" := cons (at level 60, right associativity).

  Fixpoint ne_zip {A B: Type} (l: ne_list A) (m: ne_list B) {struct l} : ne_list (A × B) :=
    match l with
    | one aone (a, head m)
    | a ::: l
        match m with
        | one bone (a, b)
        | b ::: m(a, b) ::: ne_zip l m
        end
    end.
End notations.