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.

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).