Section List.
Variables (A : Type) (B : Type) (C : Type).
Variable f : A -> B.
Proof using.
intros P H l;
apply well_founded_ind with (R := fun x y : list A => length x < length y);
auto.
apply wf_inverse_image with (R := lt); auto.
apply lt_wf.
Qed.
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.
intros P H l;
apply
well_founded_induction_type with (R := fun x y : list A => length x < length y);
auto.
apply wf_inverse_image with (R := lt); auto.
apply lt_wf.
Defined.
Proof using.
intros a l; elim l; clear l; simpl in |- *; auto.
intros H; case H.
intros a1 l H [H1| H1]; auto.
exists (nil (A:=A)); exists l; simpl in |- *; auto.
apply f_equal2 with (f := cons (A:=A)); auto.
case H; auto; intros l1 (l2, Hl2); exists (a1 :: l1); exists l2;
simpl in |- *; auto.
apply f_equal2 with (f := cons (A:=A)); auto.
Qed.
Proof using.
intros l1; elim l1; simpl in |- *; auto.
Qed.
Proof using.
intros l1; elim l1; simpl in |- *; auto.
intros a l H l2 l3 H0; apply H; injection H0; auto.
Qed.
Proof using.
intros l1 l2; generalize l1; elim l2; clear l1 l2; simpl in |- *; auto.
intros l1 l3; case l3; auto.
intros b l H; absurd (length ((b :: l) ++ l1) <= length l1).
simpl in |- *; rewrite length_app; auto with arith.
rewrite <- H; auto with arith.
intros a l H l1 l3; case l3.
simpl in |- *; intros H1; absurd (length (a :: l ++ l1) <= length l1).
simpl in |- *; rewrite length_app; auto with arith.
rewrite H1; auto with arith.
simpl in |- *; intros b l0 H0; injection H0.
intros H1 H2; apply f_equal2 with (f := cons (A:=A)); auto.
apply H with (1 := H1); auto.
Qed.
Proof using.
intros l1; elim l1; simpl in |- *; auto.
intros l2 l3 l4 a H; right; exists l3; auto.
intros a l H l2 l3 l4 a0; case l3; simpl in |- *.
intros H0; left; exists l; apply f_equal2 with (f := cons (A:=A));
injection H0; auto.
intros b l0 H0; case (H l2 l0 l4 a0); auto.
injection H0; auto.
intros (l5, H1).
left; exists l5; apply f_equal2 with (f := cons (A:=A)); injection H0; auto.
Qed.
Proof using.
intros l1; elim l1; simpl in |- *; auto.
intros l2 l3 l4 a b H; right; left; exists l3; auto.
intros a l H l2 l3 l4 a0 b; case l3; simpl in |- *.
case l; simpl in |- *.
intros H0; right; right; injection H0; split; auto.
apply f_equal2 with (f := cons (A:=A)); auto.
intros b0 l0 H0; left; exists l0; injection H0; intros;
repeat apply f_equal2 with (f := cons (A:=A)); auto.
intros b0 l0 H0; case (H l2 l0 l4 a0 b); auto.
injection H0; auto.
intros (l5, HH1); left; exists l5; apply f_equal2 with (f := cons (A:=A));
auto; injection H0; auto.
intros [H1| (H1, H2)]; auto.
right; right; split; auto; apply f_equal2 with (f := cons (A:=A)); auto;
injection H0; auto.
Qed.
Proof using.
intros a l1; elim l1; simpl in |- *; auto.
intros l2 l3; case l3; simpl in |- *; try (intros; discriminate).
intros b l H; exists (nil (A:=B)); exists l; exists b; repeat (split; auto).
intros a0 l H l2 l3; case l3; simpl in |- *; try (intros; discriminate).
intros b l0 H0.
case (H l2 l0); auto.
intros l4 (l5, (b1, (HH1, (HH2, HH3)))).
exists (b :: l4); exists l5; exists b1; repeat (simpl in |- *; split; auto).
apply f_equal2 with (f := cons (A:=B)); auto.
Qed.
Proof using.
intros b l; elim l; simpl in |- *; auto.
intros tmp; case tmp.
intros a0 l0 H [H1| H1]; auto.
exists a0; auto.
case (H H1); intros a1 (H2, H3); exists a1; auto.
Qed.
Proof using.
intros a l; elim l; simpl in |- *; auto.
intros H; case H.
intros a0 l0 H [H0| H0]; auto.
exists (snd a0); left; rewrite <- H0; case a0; simpl in |- *; auto.
case H; auto; intros l1 Hl1; exists l1; auto.
Qed.
Proof using.
intros l; elim l; simpl in |- *; auto.
Qed.
Proof using.
intros l; elim l; simpl in |- *; auto.
intros a l0 H l2; apply f_equal2 with (f := cons (A:=B)); auto.
Qed.

(* Properties of flat_map *)
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).