Definition list_length_induction :
  forall P : list A -> Type,
  (forall l1 : list A,
   (forall l2 : list A, length l2 < length l1 -> P l2) -> P l1) ->
  forall l : list A, P l.

(* Specifications: *)
Theorem in_ex_app : forall (a : A) (l : list A), In a l -> exists l1 : list A, (exists l2 : list A, l = l1 ++ a :: l2).
Theorem length_app : forall l1 l2 : list A, length (l1 ++ l2) = length l1 + length l2.
Theorem app_inv_head : forall l1 l2 l3 : list A, l1 ++ l2 = l1 ++ l3 -> l2 = l3.
Theorem app_inv_tail : forall l1 l2 l3 : list A, l2 ++ l1 = l3 ++ l1 -> l2 = l3.
Theorem app_inv_app : forall l1 l2 l3 l4 a, l1 ++ l2 = l3 ++ a :: l4 -> (exists l5 : list A, l1 = l3 ++ a :: l5) \/ (exists l5 : _, l2 = l5 ++ a :: l4).
Theorem app_inv_app2 : forall l1 l2 l3 l4 a b, l1 ++ l2 = l3 ++ a :: b :: l4 -> (exists l5 : list A, l1 = l3 ++ a :: b :: l5) \/ (exists l5 : _, l2 = l5 ++ a :: b :: l4) \/ l1 = l3 ++ a :: nil /\ l2 = b :: l4.
Theorem same_length_ex : forall (a : A) l1 l2 l3, length (l1 ++ a :: l2) = length l3 -> exists l4 : _, (exists l5 : _, (exists b : B, length l1 = length l4 /\ length l2 = length l5 /\ l3 = l4 ++ b :: l5)).
Theorem in_map_inv : forall (b : B) (l : list A), In b (map f l) -> exists a : A, In a l /\ b = f a.
Theorem in_map_fst_inv : forall a (l : list (B * C)), In a (map (fst (B:=_)) l) -> exists c : _, In (a, c) l.
Theorem length_map : forall l, length (map f l) = length l.
Theorem map_app : forall l1 l2, map f (l1 ++ l2) = map f l1 ++ map f l2.
Theorem in_flat_map : forall (l : list B) (f : B -> list C) a b, In a (f b) -> In b l -> In a (flat_map f l).
Theorem in_flat_map_ex : forall (l : list B) (f : B -> list C) a, In a (flat_map f l) -> exists b : _, In b l /\ In a (f b).