Fact list_injective_map X Y (f : X -> Y) ll :
(forall x y, f x = f y -> x = y) -> list_injective ll -> list_injective (map f ll).
Section iter.
Variable (X : Type) (f : X -> X).
Fixpoint iter x n :=
match n with
| 0   => x
| S n => iter (f x) n
end.
Fact iter_plus x a b : iter x (a+b) = iter (iter x a) b.
End iter.
Fixpoint list_repeat X (x : X) n :=
match n with
| 0   => nil
| S n => x::list_repeat x n
end.
Fact list_repeat_plus X x a b : @list_repeat X x (a+b) = list_repeat x a ++ list_repeat x b.
Fact map_list_repeat X Y f x n : @map X Y f (list_repeat x n) = list_repeat (f x) n.
Fact list_app_eq_inv X (l1 l2 r1 r2 : list X) :
l1++r1 = l2++r2 -> { m | l1++m = l2 /\ r1 = m++r2 }
+ { m | l2++m = l1 /\ r2 = m++r1 }.
Fact list_app_cons_eq_inv X (l1 l2 r1 r2 : list X) x :
l1++r1 = l2++x::r2 -> { m | l1++m = l2 /\ r1 = m++x::r2 }
+ { m | l2++x::m = l1 /\ r2 = m++r1 }.
Fact list_cons_app_cons_eq_inv X (l2 r1 r2 : list X) x y :
x::r1 = l2++y::r2 -> (l2 = nil /\ x = y /\ r1 = r2)
+ { m | l2 = x::m /\ r1 = m++y::r2 }.
Fact list_app_inj X (l1 l2 r1 r2 : list X) : length l1 = length l2 -> l1++r1 = l2++r2 -> l1 = l2 /\ r1 = r2.
Fact list_split_length X (ll : list X) k : k <= length ll -> { l : _ & { r | ll = l++r /\ length l = k } }.
Fact list_pick X (ll : list X) k : k < length ll -> { x : _ & { l : _ & { r | ll = l++x::r /\ length l = k } } }.
Fact list_split_middle X l1 (x1 : X) r1 l2 x2 r2 :
~ In x1 l2 -> ~ In x2 l1 -> l1++x1::r1 = l2++x2::r2 -> l1 = l2 /\ x1 = x2 /\ r1 = r2.
Section flat_map.
Variable (X Y : Type) (f : X -> list Y).
Fact flat_map_app l1 l2 : flat_map f (l1++l2) = flat_map f l1 ++ flat_map f l2.
Fact flat_map_app_inv l r1 y r2 : flat_map f l = r1++y::r2 -> exists l1 m1 x m2 l2, l = l1++x::l2 /\ f x = m1++y::m2
/\ r1 = flat_map f l1++m1 /\ r2 = m2++flat_map f l2.
End flat_map.
Definition prefix X (l ll : list X) := exists r, ll = l++r.
Infix "<p" := (@prefix _) (at level 70, no associativity).
Section prefix. (* as an inductive predicate *)
Variable X : Type.
Implicit Types (l ll : list X).
Fact in_prefix_0 ll : nil <p ll.
Fact in_prefix_1 x l ll : l <p ll -> x::l <p x::ll.
Fact prefix_length l m : l <p m -> length l <= length m.
Fact prefix_inv x y l ll : x::l <p y::ll -> x = y /\ l <p ll.
Fact prefix_list_inv l r rr : l++r <p l++rr -> r <p rr.
Fact prefix_refl l : l <p l.
End prefix_rect.
Fact prefix_app_inv l1 l2 r1 r2 : l1++l2 <p r1++r2 -> { l1 <p r1 } + { r1 <p l1 }.
End prefix.
Definition prefix_spec X (l ll : list X) : l <p ll -> { r | ll = l ++ r }.
Fact prefix_app_lft_inv X (l1 l2 m : list X) : l1++l2 <p m -> { m2 | m = l1++m2 /\ l2 <p m2 }.
Section list_assoc.
Variables (X Y : Type) (eq_X_dec : eqdec X).
Fixpoint list_assoc x l : option Y :=
match l with
| nil  => None
| (y,a)::l => if eq_X_dec x y then Some a else list_assoc x l
end.
Fact list_assoc_eq x y l x' : x = x' -> list_assoc x' ((x,y)::l) = Some y.
Fact list_assoc_neq x y l x' : x <> x' -> list_assoc x' ((x,y)::l) = list_assoc x' l.
Fact list_assoc_In x l :
match list_assoc x l with
| None   => ~ In x (map fst l)
| Some y => In (x,y) l
end.
Fact In_list_assoc x l : In x (map fst l) -> { y | list_assoc x l = Some y /\ In (x,y) l }.
Fact not_In_list_assoc x l : ~ In x (map fst l) -> list_assoc x l = None.
Fact list_assoc_app x ll mm : list_assoc x (ll++mm)
= match list_assoc x ll with
| None   => list_assoc x mm
| Some y => Some y
end.
End list_assoc.
Section list_first_dec.
Variable (X : Type) (P : X -> Prop) (Pdec : forall x, { P x } + { ~ P x }).

(* Specifications: *)
Theorem list_choose_dec ll : { l : _ & { x : _ & { r | ll = l++x::r /\ P x /\ forall y, In y l -> ~ P y } } }
+ { forall x, In x ll -> ~ P x }.
Theorem list_first_dec a ll : P a -> In a ll -> { l : _ & { x : _ & { r | ll = l++x::r /\ P x /\ forall y, In y l -> ~ P y } } }.
End list_first_dec.