Library rt.util.list

Require Import rt.util.tactics.

(* Lemmas about lists without duplicates. *)
Section UniqList.

  Lemma idx_lt_rcons :
     {T: eqType} (l: seq T) i x0,
      uniq l
      i < size l
      [seq x <- l | index x l < i.+1] =
        rcons [seq x <- l | index x l < i] (nth x0 l i).

  Lemma filter_idx_lt_take :
     {T: eqType} (l: seq T) i,
      uniq l
      i < size l
      [seq x <- l | index x l < i] = take i l.

  Lemma filter_idx_le_takeS :
     {T: eqType} (l: seq T) i,
      uniq l
      i < size l
      [seq x <- l | index x l i] = take i.+1 l.

End UniqList.

(* Additional lemmas about list zip. *)
Section Zip.

  Lemma zipP {T: eqType} (x0: T) (P: _ _ bool) (X Y: seq T):
    size X = size Y
    reflect ( i, i < size (zip X Y) P (nth x0 X i) (nth x0 Y i))
            (all (fun pP (fst p) (snd p)) (zip X Y)).

  Lemma mem_zip_exists :
     (T T': eqType) (x1: T) (x2: T') l1 l2 elem elem',
      size l1 = size l2
      (x1, x2) \in zip l1 l2
       idx,
        idx < size l1
        idx < size l2
        x1 = nth elem l1 idx
        x2 = nth elem' l2 idx.

End Zip.

(* Restate nth_error function from Coq library. *)
Fixpoint nth_or_none {T: Type} (l: seq T) (n:nat) {struct n} : option T :=
  match n, l with
  | 0, x :: _Some x
  | n.+1, _ :: lnth_or_none l n
  | _, _None
end.

(* Lemmas about nth_or_none. *)
Section NthOrNone.

  Context {T: eqType}.

  Lemma nth_or_none_mem :
     (l: seq T) n x, nth_or_none l n = Some x x \in l.

  Lemma nth_or_none_mem_exists :
     (l: seq T) x, x \in l n, nth_or_none l n = Some x.

  Lemma nth_or_none_size_none :
     (l: seq T) n,
      nth_or_none l n = None n size l.

  Lemma nth_or_none_size_some :
     (l: seq T) n x,
      nth_or_none l n = Some x n < size l.

  Lemma nth_or_none_uniq :
     (l: seq T) i j x,
      uniq l
      nth_or_none l i = Some x
      nth_or_none l j = Some x
      i = j.

Lemma nth_or_none_nth :
     (l: seq T) n x x0,
      nth_or_none l n = Some x
      nth x0 l n = x.

End NthOrNone.