Library CoLoR.Util.List.ListUtil
CoLoR, a Coq library on rewriting and termination.
See the COPYRIGHTS and LICENSE files.
- Stephane Le Roux, 2006-10-17
- Adam Koprowski, 2006-04-28
- Solange Coupet-Grimal and William Delobel, 2006-01-09
- Frederic Blanqui, 2005-02-03, 2009-07-06
- Sebastien Hinderer, 2004-05-25
Set Implicit Arguments.
Require Import LogicUtil NatUtil EqUtil Setoid SetoidList RelMidex Omega
Relations BoolUtil.
Require Export List.
Require Program.
Implicit Arguments in_app_or [A l m a].
Implicit Arguments in_map [A B l x].
Implicit Arguments in_combine_l [A B l l' x y].
Implicit Arguments in_combine_r [A B l l' x y].
Implicit Arguments nth_In [A n l].
Ltac elt_type l := match type of l with list ?A => A end.
Infix "[=" := incl (at level 70).
membership
Section In.
Variable A : Type.
Lemma in_app : forall l m (x : A), In x (l ++ m) <-> In x l \/ In x m.
Lemma notin_app : forall l m (x : A), ~In x (l ++ m) <-> ~In x l /\ ~In x m.
Lemma in_appl : forall (x : A) l1 l2, In x l1 -> In x (l1 ++ l2).
Lemma in_appr : forall (x : A) l1 l2, In x l2 -> In x (l1 ++ l2).
Lemma in_app_com : forall (x : A) l1 l2 l3,
In x ((l1 ++ l3) ++ l2) -> In x ((l1 ++ l2) ++ l3).
Lemma in_elim : forall (x : A) l,
In x l -> exists l1, exists l2, l = l1 ++ x :: l2.
Variable eqA_dec : forall x y : A, {x=y}+{~x=y}.
Lemma in_elim_dec : forall (x : A) l,
In x l -> exists m, exists p, l = m ++ x :: p /\ ~In x m.
Lemma In_midex : eq_midex A -> forall (x : A) l, In x l \/ ~In x l.
Lemma In_elim_right : eq_midex A -> forall (x : A) l,
In x l -> exists l', exists l'', l = l'++x::l'' /\ ~In x l''.
Lemma In_cons : forall (x a : A) l, In x (a::l) <-> a=x \/ In x l.
Lemma In_InA_eq : forall (x : A) l, In x l <-> InA eq x l.
End In.
Implicit Arguments in_elim [A x l].
Implicit Arguments in_elim_dec [A x l].
Ltac intac := repeat (apply in_eq || apply in_cons).
Ltac list_ok := let x := fresh in intro x;
match goal with
| |- In _ ?l => vm_compute; destruct x; tauto
end.
inclusion
Add Parametric Relation (A : Type) : (list A) (@incl A)
reflexivity proved by (@incl_refl A)
transitivity proved by (@incl_tran A)
as incl_rel.
Add Parametric Morphism (A : Type) : (@app A)
with signature (@incl A) ==> (@incl A) ==> (@incl A)
as app_incl.
Section incl.
Variable A : Type.
Lemma incl_nil_elim : forall l : list A, l [= nil <-> l = nil.
Lemma incl_nil : forall l : list A, nil [= l.
Lemma incl_cons_l : forall (a : A) l m, a :: l [= m -> In a m /\ l [= m.
Lemma incl_cons_l_in : forall (x : A) l m, x :: l [= m -> In x m.
Lemma incl_cons_l_incl : forall (x : A) l m, x :: l [= m -> l [= m.
Lemma incl_app_elim : forall l1 l2 l3 : list A,
l1 ++ l2 [= l3 -> l1 [= l3 /\ l2 [= l3.
Lemma incl_appr_incl : forall l1 l2 l3 : list A, l1 ++ l2 [= l3 -> l1 [= l3.
Lemma incl_appl_incl : forall l1 l2 l3 : list A, l1 ++ l2 [= l3 -> l2 [= l3.
Lemma appl_incl : forall l l2 l2' : list A, l2 [= l2' -> l ++ l2 [= l ++ l2'.
Lemma appr_incl : forall l l1 l1' : list A, l1 [= l1' -> l1 ++ l [= l1' ++ l.
Lemma app_com_incl : forall l1 l2 l3 l4 : list A,
(l1 ++ l3) ++ l2 [= l4 -> (l1 ++ l2) ++ l3 [= l4.
Lemma incl_cons_r : forall x : A, forall m l, l [= x :: m -> In x l \/ l [= m.
Variable eqA_dec : forall x y : A, {x=y}+{~x=y}.
Lemma not_incl : forall l m, ~ l [= m <-> exists x:A, In x l /\ ~In x m.
End incl.
Implicit Arguments incl_app_elim [A l1 l2 l3].
strict inclusion
Definition strict_incl A (l m : list A) := l [= m /\ ~m [= l.
Infix "[" := strict_incl (at level 70).
Lemma strict_incl_tran : forall A (l m n : list A), l [ m -> m [ n -> l [ n.
Add Parametric Relation (A : Type) : (list A) (@strict_incl A)
transitivity proved by (@strict_incl_tran A)
as strict_incl_rel.
equivalence
Section equiv.
Variable A : Type.
Definition lequiv (l1 l2 : list A) : Prop := l1 [= l2 /\ l2 [= l1.
Lemma lequiv_refl : forall l, lequiv l l.
Lemma lequiv_sym : forall l1 l2, lequiv l1 l2 -> lequiv l2 l1.
Lemma lequiv_trans :
forall l1 l2 l3, lequiv l1 l2 -> lequiv l2 l3 -> lequiv l1 l3.
End equiv.
Infix "[=]" := lequiv (at level 70).
Add Parametric Relation (A : Type) : (list A) (@lequiv A)
reflexivity proved by (@lequiv_refl A)
symmetry proved by (@lequiv_sym A)
transitivity proved by (@lequiv_trans A)
as lequiv_rel.
Add Parametric Morphism (A : Type) : (@app A)
with signature (@lequiv A) ==> (@lequiv A) ==> (@lequiv A)
as app_lequiv.
empty list
Section nil.
Variable A : Type.
Lemma list_empty_dec : forall l : list A, {l = nil} + {l <> nil}.
Definition is_empty (l : list A) : bool :=
match l with
| nil => true
| _ => false
end.
End nil.
cons
Add Parametric Morphism (A : Type) : (@cons A)
with signature (@eq A) ==> (@incl A) ==> (@incl A)
as incl_double_cons.
Add Parametric Morphism (A : Type) : (@cons A)
with signature (@eq A) ==> (@lequiv A) ==> (@lequiv A)
as cons_lequiv.
Section cons.
Variable A : Type.
Lemma cons_eq : forall x x' : A, forall l l',
x = x' -> l = l' -> x :: l = x' :: l'.
Lemma head_eq : forall x x' : A, forall l, x = x' -> x :: l = x' :: l.
Lemma tail_eq : forall x : A, forall l l', l = l' -> x :: l = x :: l'.
End cons.
append
Section app.
Variable A : Type.
Lemma length_app : forall l m : list A, length (l ++ m) = length l + length m.
Lemma app_nil : forall l1 l2 : list A, l1 = nil -> l2 = nil -> l1 ++ l2 = nil.
Lemma app_eq : forall l1 l2 l1' l2' : list A,
l1 = l1' -> l2 = l2' -> l1 ++ l2 = l1' ++ l2'.
Lemma appl_eq : forall l1 l2 l1' : list A, l1 = l1' -> l1 ++ l2 = l1' ++ l2.
Lemma appr_eq : forall l1 l2 l2' : list A, l2 = l2' -> l1 ++ l2 = l1 ++ l2'.
Lemma list_app_first_last : forall l m (a : A),
(l ++ a::nil) ++ m = l ++ a::m.
Lemma list_app_last : forall l m n (a : A),
l ++ m = n ++ a::nil -> m <> nil -> In a m.
Lemma list_drop_last : forall l m n (a : A),
l ++ m = n ++ a::nil -> m <> nil -> exists2 w, w [= m & l ++ w = n.
Lemma last_intro : forall l : list A, length l > 0 ->
exists m, exists a, l = m ++ a :: nil /\ length m = length l - 1.
End app.
length
Section length.
Variable A : Type.
Lemma length_0 : forall l : list A, length l = 0 -> l = nil.
End length.
Implicit Arguments length_0 [A l].
head & tail
Section head_tail.
Variable A : Type.
Lemma head_app : forall (l l': list A) (lne: l <> nil),
head (l ++ l') = head l.
Lemma length_tail : forall l : list A, length (tail l) <= length l.
Lemma tail_in : forall (x: A) l, In x (tail l) -> In x l.
Lemma tail_cons_tail : forall (l1 l2: list A),
l1 <> nil -> tail l1 ++ l2 = tail (l1 ++ l2).
Lemma length_tail_minus : forall (l : list A), length (tail l) = length l - 1.
Lemma list_decompose_head : forall (l : list A) el (lne: l <> nil),
head l = Some el -> l = el :: tail l.
Lemma in_head_tail : forall a (l : list A),
In a l -> Some a = head l \/ In a (tail l).
Lemma head_notNil : forall (l : list A) (lne : l <> nil),
{a : A | head l = Some a}.
Lemma head_of_notNil : forall (l : list A) a (lne: l <> nil),
head l = Some a -> proj1_sig (head_notNil lne) = a.
End head_tail.
Hint Resolve tail_in tail_cons_tail head_app : datatypes.
Hint Rewrite head_app length_app : datatypes.
tail_nth
Section tail_nth.
Variable A : Type.
Fixpoint tail_nth (l : list A) (n : nat) : option (list A) :=
match l, n with
| _, 0 => Some l
| a :: l', S n' => tail_nth l' n'
| _, _ => None
end.
End tail_nth.
list filtering
Section filter.
Variables (A : Type) (f : A -> bool).
Lemma filter_app : forall l m, filter f (l ++ m) = filter f l ++ filter f m.
Lemma filter_incl : forall l, filter f l [= l.
Variable eq_dec : forall x y : A, {x=y}+{~x=y}.
Lemma notIn_filter : forall x l,
~In x (filter f l) <-> ~In x l \/ (In x l /\ f x = false).
End filter.
Section filter_opt.
Variables (A B : Type) (f : A -> option B).
Fixpoint filter_opt (l : list A) : list B :=
match l with
| nil => nil
| cons a m =>
match f a with
| Some b => cons b (filter_opt m)
| _ => filter_opt m
end
end.
End filter_opt.
boolean membership when the equality on A is decidable
Section Inb.
Variables (A : Type) (eq_dec : forall x y : A, {x=y}+{~x=y}).
Fixpoint Inb (x : A) (l : list A) : bool :=
match l with
| nil => false
| cons y l' =>
match eq_dec x y with
| left _ => true
| _ => Inb x l'
end
end.
Lemma Inb_true : forall x l, Inb x l = true -> In x l.
Lemma Inb_false : forall x l, Inb x l = false -> In x l -> False.
Lemma Inb_intro : forall x l, In x l -> Inb x l = true.
Lemma Inb_elim : forall x l, ~In x l -> Inb x l = false.
Lemma Inb_correct : forall x l, In x l <-> Inb x l = true.
Lemma Inb_incl : forall x l l', l [= l' -> Inb x l = true -> Inb x l' = true.
Lemma Inb_equiv : forall x l l', lequiv l l' -> Inb x l = Inb x l'.
Definition Inclb (l1 l2 : list A) := forallb (fun x => Inb x l2) l1.
Lemma Inclb_ok : forall l1 l2, Inclb l1 l2 = true <-> l1 [= l2.
End Inb.
Ltac inbtac :=
match goal with
| _ : In ?x ?l |- _ =>
let H0 := fresh "H" in
(assert (H0 : Inb x l = true); apply Inb_intro; hyp; rewrite H0)
end.
remove
Section remove.
Variables (A : Type) (eq_dec : forall x y : A, {x=y}+{~x=y}).
Fixpoint remove (y : A) (l : list A) : list A :=
match l with
| nil => nil
| cons x l' =>
match eq_dec x y with
| left _ => remove y l'
| right _ => cons x (remove y l')
end
end.
Lemma length_remove : forall (x : A) l, length (remove x l) <= length l.
Lemma In_length_remove : forall (x : A) l,
In x l -> length (remove x l) < length l.
Lemma In_remove : forall (x y : A) l, x <> y -> In y l -> In y (remove x l).
Lemma incl_remove : forall (x : A) l m, ~In x l -> l [= m -> l [= remove x m.
Lemma notin_remove : forall x l, In x (remove x l) -> False.
Lemma remove_In : forall a x l, In a (remove x l) -> In a l.
Lemma remove_eq : forall a x l, In a (remove x l) <-> a <> x /\ In a l.
End remove.
removes
Section removes.
Variable (A : Type) (eqdec : forall x y : A, {x=y}+{x<>y}).
Notation In_dec := (In_dec eqdec).
Fixpoint removes (l m : list A) : list A :=
match m with
| nil => nil
| x :: m' =>
match In_dec x l with
| left _ => removes l m'
| right _ => x :: removes l m'
end
end.
Lemma incl_removes : forall l m, removes l m [= m.
Lemma incl_removes_app : forall l m, m [= removes l m ++ l.
Lemma In_removes : forall x l m, In x (removes l m) <-> In x m /\ ~In x l.
End removes.
map
Section map.
Variable (A B : Type) (f : A->B).
Lemma map_app : forall l1 l2, map f (l1 ++ l2) = (map f l1) ++ map f l2.
Lemma in_map_elim : forall x l, In x (map f l) -> exists y, In y l /\ x = f y.
Lemma map_eq : forall (g : A->B) l,
(forall x, In x l -> f x = g x) -> map f l = map g l.
End map.
Implicit Arguments in_map_elim [A B f x l].
Lemma map_eq_id : forall A (f:A->A) l,
(forall x, In x l -> f x = x) -> map f l = l.
flat_map
Section flat_map.
Variables (A B : Type) (f : A -> list B).
Lemma In_flat_map_intro : forall x l y,
In y l -> In x (f y) -> In x (flat_map f l).
Lemma In_flat_map_elim : forall l y,
In y (flat_map f l) -> exists x, In x l /\ In y (f x).
Lemma flat_map_app : forall l m,
flat_map f (l ++ m) = flat_map f l ++ flat_map f m.
End flat_map.
flattening
Section flat.
Variable A : Type.
Fixpoint flat (l : list (list A)) : list A :=
match l with
| nil => nil
| cons x l' => x ++ flat l'
end.
Lemma In_incl_flat : forall x l, In x l -> x [= flat l.
Lemma incl_flat_In : forall x c cs l,
In x c -> In c cs -> flat cs [= l -> In x l.
End flat.
Implicit Arguments In_incl_flat [A x l].
element & replacement at a position
Section Element_At_List.
Variable A : Type.
Fixpoint element_at (l : list A) (p : nat) : option A :=
match l with
| nil => None
| h :: t =>
match p with
| 0 => Some h
| S p' => element_at t p'
end
end.
Notation "l '[' p ']'" := (element_at l p) (at level 50).
Fixpoint replace_at (l : list A) (p : nat) (a : A) : list A :=
match l with
| nil => nil
| h :: t =>
match p with
| 0 => a :: t
| S p' => h :: (replace_at t p' a)
end
end.
Notation "l '[' p ':=' a ']'" := (replace_at l p a) (at level 50).
Lemma element_at_exists : forall l p,
p < length l <-> ex (fun a => l[p] = Some a).
Lemma element_at_replaced : forall l p a, p < length l -> l[p:=a][p] = Some a.
Lemma element_at_not_replaced : forall l p q a, p <> q -> l[p] = l[q:=a][p].
Lemma in_exists_element_at :
forall l a, In a l -> ex (fun p => l[p] = Some a).
Lemma exists_element_at_in :
forall l a, ex (fun p => l[p] = Some a) -> In a l.
Lemma element_at_in : forall (x:A) l n, l[n] = Some x -> In x l.
Lemma element_at_in2 :
forall (x:A) l n, l[n] = Some x -> In x l /\ n < length l.
Lemma element_at_app_r : forall l l' p,
p >= length l -> (l ++ l') [p] = l' [p - length l].
Lemma replace_at_app_r : forall l l' p a,
p >= length l -> (l ++ l') [p := a] = l ++ l' [p - length l := a].
End Element_At_List.
Implicit Arguments element_at_in [A x l n].
Implicit Arguments element_at_in2 [A x l n].
Implicit Arguments in_exists_element_at [A l a].
Implicit Arguments element_at_exists [A l p].
Notation "l '[' p ']'" := (element_at l p) (at level 50) : list_scope.
Notation "l '[' p ':=' a ']'" := (replace_at l p a) (at level 50) : list_scope.
one_less
Section one_less.
Variables (A : Type) (r : relation A).
Inductive one_less : relation (list A) :=
| one_less_cons : forall (l l' : list A) (p : nat) (a a' : A),
r a a' -> l[p] = Some a -> l' = l[p:=a'] -> one_less l l'.
Lemma one_less_length : forall l l', one_less l l' -> length l = length l'.
End one_less.
Implicit Arguments one_less [A].
Implicit Arguments one_less_cons [A].
reverse
Section reverse.
Variable A : Type.
Lemma in_rev : forall (x : A) l, In x l -> In x (rev l).
Lemma incl_rev : forall l : list A, l [= rev l.
Lemma rev_incl : forall l : list A, rev l [= l.
Lemma incl_rev_intro : forall l l' : list A, rev l [= rev l' -> l [= l'.
End reverse.
Section reverse_tail_recursive.
Variable A : Type.
Fixpoint rev_append (l' l : list A) : list A :=
match l with
| nil => l'
| a :: l => rev_append (a :: l') l
end.
Notation rev' := (rev_append nil).
Lemma rev_append_rev : forall l l', rev_append l' l = rev l ++ l'.
Lemma rev_append_app : forall l l' acc : list A,
rev_append acc (l ++ l') = rev_append (rev_append acc l) l'.
Lemma rev'_app : forall l l' : list A, rev' (l ++ l') = rev' l' ++ rev' l.
Lemma rev'_rev : forall l : list A, rev' l = rev l.
Lemma rev'_rev' : forall l : list A, rev' (rev' l) = l.
Lemma rev'_cons : forall a (l : list A), rev' (a::l) = rev' l ++ (a::nil).
End reverse_tail_recursive.
Notation rev' := (rev_append nil).
split
Section split.
Variable A : Type.
Fixpoint split_aux (acc l : list A) (n : nat) : option (list A * list A) :=
match l, n with
| _, 0 => Some (rev' acc, l)
| a :: l', S n' => split_aux (a::acc) l' n'
| _, _ => None
end.
Lemma split_aux_correct : forall l n l1 l2 acc,
split_aux acc l n = Some (l1, l2) -> rev' acc ++ l = l1 ++ l2.
Implicit Arguments split_aux_correct [l n l1 l2].
Notation split := (split_aux nil).
Lemma split_correct : forall l n l1 l2,
split l n = Some (l1, l2) -> l = l1 ++ l2.
End split.
Notation split := (split_aux nil).
Implicit Arguments split_correct [A l n l1 l2].
last element
Section last.
Variable A : Type.
Lemma last_nth : forall (d : A) l, last l d = nth (length l - 1) l d.
Lemma last_default : forall (d1 : A) d2 l, l <> nil -> last l d1 = last l d2.
End last.
Implicit Arguments last_intro [A l].
partition
Section partition.
Variables (A : Type) (f : A -> bool) (a : A) (l : list A).
Lemma partition_complete : let p := partition f l in
In a l -> In a (fst p) \/ In a (snd p).
Lemma partition_inleft : In a (fst (partition f l)) -> In a l.
Lemma partition_inright : In a (snd (partition f l)) -> In a l.
Lemma partition_left : In a (fst (partition f l)) -> f a = true.
Lemma partition_right : In a (snd (partition f l)) -> f a = false.
End partition.
Section partition_by_prop.
Variables (A : Type) (P : A -> Prop) (P_dec : forall x, {P x}+{~P x}).
Definition partition_by_prop a :=
match P_dec a with
| left _ => true
| right _ => false
end.
Lemma partition_by_prop_true : forall a, partition_by_prop a = true -> P a.
End partition_by_prop.
Section partition_by_rel.
Variables (A : Type) (R : relation A) (R_dec : rel_dec R).
Definition partition_by_rel p :=
if R_dec (fst p) (snd p) then true else false.
Lemma partition_by_rel_true : forall a b,
partition_by_rel (a, b) = true -> R a b.
End partition_by_rel.
listfilter
Section ListFilter.
Variable A : Type.
Fixpoint listfilter (L : list A) l :=
match L with
| nil => nil
| a :: Q =>
match l with
| nil => nil
| true :: q => a :: listfilter Q q
| false :: q => listfilter Q q
end
end.
Lemma listfilter_in : forall L l i x,
L[i]=Some x -> l[i]=Some true -> In x (listfilter L l) .
End ListFilter.
nth/nth_error
Section ListsNth.
Variable A: Type.
Lemma In_nth : forall A d (x : A) l,
In x l -> exists i, i < length l /\ nth i l d = x.
Lemma nth_error_In : forall (l : list A) i,
{a : A | nth_error l i = Some a} + {nth_error l i = None}.
Lemma nth_some_in :
forall (l : list A) i a, nth_error l i = Some a -> In a l.
Lemma list_In_nth : forall (l : list A) a,
In a l -> exists p: nat, nth_error l p = Some a.
Lemma nth_app_left : forall (l m: list A) i,
i < length l -> nth_error (l ++ m) i = nth_error l i.
Lemma nth_app_right : forall (l m: list A) i, i >= length l ->
nth_error (l ++ m) i = nth_error m (i - length l).
Lemma nth_app : forall (l m: list A) a i, nth_error (l ++ m) i = Some a ->
(nth_error l i = Some a /\ i < length l) \/
(nth_error m (i - length l) = Some a /\ i >= length l).
Lemma nth_beyond : forall (l : list A) i,
i >= length l -> nth_error l i = None.
Lemma nth_beyond_idx : forall (l : list A) i,
nth_error l i = None -> i >= length l.
Lemma nth_in : forall (l : list A) i,
nth_error l i <> None <-> i < length l.
Lemma nth_some : forall (l : list A) n a,
nth_error l n = Some a -> n < length l.
Lemma nth_map_none : forall (l : list A) i (f: A -> A),
nth_error l i = None -> nth_error (map f l) i = None.
Lemma nth_map_none_rev : forall (l : list A) i (f: A -> A),
nth_error (map f l) i = None -> nth_error l i = None.
Lemma nth_map_some : forall (l : list A) i (f: A -> A) a,
nth_error l i = Some a -> nth_error (map f l) i = Some (f a).
Lemma nth_map_some_rev : forall (l : list A) i (f: A -> A) a,
nth_error (map f l) i = Some a ->
exists a', nth_error l i = Some a' /\ f a' = a.
Lemma nth_error_singleton_in : forall (a b: A) i,
nth_error (a :: nil) i = Some b -> a = b /\ i = 0.
End ListsNth.
Implicit Arguments In_nth [A x l].
ith
Section ith.
Variable A : Type.
Fixpoint ith (l : list A) : forall i, i < length l -> A :=
match l as l return forall i, i < length l -> A with
| nil => fun i H => False_rect A (lt_n_O i H)
| cons x m => fun i =>
match i return i < S (length m) -> A with
| O => fun _ => x
| S j => fun H => ith (lt_S_n H)
end
end.
Lemma ith_In : forall l i (h : i < length l), In (ith h) l.
Lemma ith_eq : forall l i (hi : i < length l) j (hj : j < length l),
i = j -> ith hi = ith hj.
Lemma ith_eq_app : forall m l i (hi : i < length (l++m))
j (hj : j < length l), i = j -> ith hi = ith hj.
End ith.
Implicit Arguments ith_In [A l i].
list of values of a function
Section values.
Variables (A : Type) (f : nat -> A).
Fixpoint values j : list A :=
match j with
| 0 => nil
| S k => f k :: values k
end.
End values.
list of values of a partial function
Section pvalues.
Variable A : Type.
Fixpoint pvalues n : (forall i, i < n -> A) -> list A :=
match n as n return (forall i, i < n -> A) -> list A with
| 0 => fun _ => nil
| S k => fun f =>
f 0 (lt_O_Sn k) :: pvalues (fun i h => f (S i) (lt_n_S h))
end.
Lemma pvalues_eq : forall n (f g : forall i, i < n -> A),
(forall i (hi : i < n), f i hi = g i hi) -> pvalues f = pvalues g.
End pvalues.
Section pvalues_map.
Variables (A B : Type) (f : A -> B).
Definition f_ith (l : list A) i (hi : i < length l) := f (ith hi).
Lemma pvalues_ith_eq_map : forall l, pvalues (@f_ith l) = map f l.
End pvalues_map.
lists of bounded natural numbers
Definition nat_lts n := list (nat_lt n).
Lemma in_map_val : forall n (l : nat_lts n) i, In i (map (@val n) l) -> i<n.
Implicit Arguments in_map_val [n l i].
Section mk_nat_lts.
Variable n : nat.
Lemma mk_nat_lts_aux1 : forall k', S k' < n -> k' < n.
Fixpoint mk_nat_lts_aux k :=
match k as k return k<n -> list (nat_lt n) with
| 0 => fun h => mk_nat_lt h :: nil
| S k' => fun h => mk_nat_lt h :: mk_nat_lts_aux k' (mk_nat_lts_aux1 h)
end.
Lemma mk_nat_lts_aux_correct : forall x k (h : k<n) i,
i <= k -> val (nth i (mk_nat_lts_aux h) x) = k - i.
Lemma mk_nat_lts_aux_complete : forall k (h : k<n) i (p : i<n),
i <= k -> In (mk_nat_lt p) (mk_nat_lts_aux h).
End mk_nat_lts.
Implicit Arguments mk_nat_lts_aux [].
Definition mk_nat_lts n :=
match n return list (nat_lt n) with
| 0 => nil
| S p => mk_nat_lts_aux (S p) p (le_n (S p))
end.
Implicit Arguments mk_nat_lts [].
Lemma mk_nat_lts_correct : forall n x i,
i < n -> val (nth i (mk_nat_lts n) x) = pred n - i.
Lemma mk_nat_lts_complete : forall n i (p : i<n),
In (mk_nat_lt p) (mk_nat_lts n).
first element satisfying some boolean predicate
Section first.
Variable (A : Type) (f : A -> bool).
Fixpoint first l :=
match l with
| nil => None
| x :: l' => if f x then Some x else first l'
end.
End first.
transpose
Instance transpose_m' A B : Proper (@inclusion B ==> Logic.eq ==> impl)
(@transpose A B).
Instance transpose_m A B : Proper (@same_relation B ==> Logic.eq ==> iff)
(@transpose A B).
fold_left
Section fold_left.
Variables (A : Type) (eqA : relation A) (B : Type) (eqB : relation B).
Definition feq f f' :=
forall a a', eqA a a' -> forall b b', eqB b b' -> eqA (f a b) (f' a' b').
Global Instance fold_left_m_ext :
Proper (feq ==> eqlistA eqB ==> eqA ==> eqA) (@fold_left A B).
End fold_left.
Section fold_left_list.
Variables (A B : Type) (f : list A -> B -> list A).
Variable g : B -> list A.
Variable hyp : forall l b, f l b = g b ++ l.
Lemma fold_left_flat_map : forall bs l,
fold_left f bs l = flat_map g (rev bs) ++ l.
Lemma In_fold_left : forall a bs l,
In a (fold_left f bs l) <-> (In a l \/ exists b, In b bs /\ In a (g b)).
End fold_left_list.
Implicit Arguments fold_left_flat_map [A B f].
Implicit Arguments In_fold_left [A B f].
checking a boolean property P 0 && ... && P (n-1), where the domain of
the predicate P is restricted to numbers smaller than n.
Section Check_seq_aux.
Variables (n : nat) (Pr : nat_lt n -> Prop)
(P : forall i : nat_lt n, Exc (Pr i)).
Program Fixpoint check_seq_aux p (H : forall i : nat_lt n, val i < p -> Pr i)
{measure (n - p)} : Exc (forall i : nat_lt n, Pr i) :=
match le_lt_dec n p with
| left _ => value _
| right cmp =>
match @P (mk_nat_lt cmp) with
| error => error
| value _ => @check_seq_aux (S p) _ _
end
end.
End Check_seq_aux.
Program Definition check_seq (n : nat) (Pr : nat_lt n -> Prop)
(P : forall (i : nat_lt n), Exc (Pr i)) :
Exc (forall (i : nat_lt n), Pr i) :=
check_seq_aux P (p:=0) _.
lookup el default l takes an association list of pairs of keys, values
and returns v such that (el, v) belongs to the list, or default
if there is no element with key equal to el.
Section lookup.
Variable (A B : Type).
Variable (eqA_dec : forall x y : A, {x = y} + {x <> y}).
Variable (el : A).
Variable (default : B).
Fixpoint lookup (l : list (A * B)) : B :=
match l with
| nil => default
| (el', v)::l' =>
if @eqA_dec el el' then
v
else
lookup l'
end.
Variable P : B -> Prop.
Lemma lookup_prop l :
(forall x, In x l -> P (snd x)) -> P default -> P (lookup l).
End lookup.
lookup_dep is equivalent to lookup above but works on lists of
dependent pairs instead.
Section lookup_dep.
Variable (A : Type) (B : A -> Type).
Variable (eqA_dec : forall x y : A, {x = y} + {x <> y}).
Variable (el : A).
Variable (default : forall a : A, B a).
Program Fixpoint lookup_dep (l : list { el : A & B el}) : B el :=
match l with
| nil => @default el
| x::l' =>
let (el', v) := x in
if @eqA_dec el el' then
v
else
lookup_dep l'
end.
Variable P : forall a : A, B a -> Prop.
Lemma lookup_dep_prop (l : list {el : A & B el}) :
(forall x, In x l -> P (projT2 x)) ->
(forall a : A, P (@default a)) -> P (lookup_dep l).
End lookup_dep.
forallb
Section forallb.
Variables (A : Type) (P : A -> Prop)
(f : A -> bool) (f_ok : forall x, f x = true <-> P x).
Lemma forallb_false : forall l,
forallb f l = false <-> exists x, In x l /\ f x = false.
Lemma forallb_neg : forall l,
forallb f l = false <-> exists x, In x l /\ ~P x.
Variables (As : list A) (As_ok : forall x, In x As).
Lemma forallb_ok_fintype : forallb f As = true <-> forall x, P x.
End forallb.
sub_list
Section sub_list.
Variable A : Type.
Fixpoint sub_list l k n : list A :=
match l, k, n with
| _ :: l', S k', _ => sub_list l' k' n
| x :: l', 0, S n' => x :: sub_list l' 0 n'
| _, _, _ => nil
end.
Functional Scheme sub_list_ind := Induction for sub_list Sort Prop.
Lemma sub_list_ok : forall l k n i,
k < length l -> k+n <= length l -> i < n ->
element_at (sub_list l k n) i = element_at l (k+i).
Lemma length_sub_list : forall l k n,
k < length l -> k+n <= length l -> length (sub_list l k n) = n.
Lemma eq_app_elim_l : forall l1 l l2,
l = l1 ++ l2 -> l1 = sub_list l 0 (length l1).
Lemma eq_app_elim_r : forall l1 l l2,
l = l1 ++ l2 -> l2 = sub_list l (length l1) (length l2).
Lemma sub_list_0 : forall l k, sub_list l k 0 = nil.
Lemma sub_list_length : forall l, sub_list l 0 (length l) = l.
Lemma app_eq_sub_list : forall l1 l2, l1++l2 =
sub_list (l1++l2) 0 (length l1)
++ sub_list (l1++l2) (length l1) (length l2).
End sub_list.
Implicit Arguments eq_app_elim_l [A l1 l l2].
Implicit Arguments eq_app_elim_r [A l1 l l2].
natural numbers from n-1 to 0
Fixpoint nats_decr_lt n :=
match n with
| 0 => nil
| S n' => n' :: nats_decr_lt n'
end.
Definition nats_incr_lt n := rev' (nats_decr_lt n).
Lemma In_nats_decr_lt : forall n x, x < n <-> In x (nats_decr_lt n).