(** [list_forall2 P [x1 ... xN] [y1 ... yM]] holds iff [N = M] and [P xi yi] holds for all [i]. *)
Section FORALL2.
Variable A: Type.
Variable B: Type.
Variable P: A -> B -> Prop.
Inductive list_forall2: list A -> list B -> Prop :=
| list_forall2_nil:
list_forall2 nil nil
| list_forall2_cons:
forall a1 al b1 bl,
P a1 b1 ->
list_forall2 al bl ->
list_forall2 (a1 :: al) (b1 :: bl).

(* Specifications: *)
Lemma list_forall2_app:
forall a2 b2 a1 b1,
list_forall2 a1 b1 -> list_forall2 a2 b2 ->
list_forall2 (a1 ++ a2) (b1 ++ b2).
Lemma list_forall2_length:
forall l1 l2,
list_forall2 l1 l2 -> length l1 = length l2.
Lemma list_forall2_in_left:
forall x1 l1 l2,
list_forall2 l1 l2 -> In x1 l1 -> exists x2, In x2 l2 /\ P x1 x2.
Lemma list_forall2_in_right:
forall x2 l1 l2,
list_forall2 l1 l2 -> In x2 l2 -> exists x1, In x1 l1 /\ P x1 x2.
Lemma list_forall2_app:
forall a2 b2 a1 b1,
list_forall2 a1 b1 -> list_forall2 a2 b2 ->
list_forall2 (a1 ++ a2) (b1 ++ b2).
Lemma list_forall2_length:
forall l1 l2,
list_forall2 l1 l2 -> length l1 = length l2.
Lemma list_forall2_in_left:
forall x1 l1 l2,
list_forall2 l1 l2 -> In x1 l1 -> exists x2, In x2 l2 /\ P x1 x2.
Lemma list_forall2_in_right:
forall x2 l1 l2,
list_forall2 l1 l2 -> In x2 l2 -> exists x1, In x1 l1 /\ P x1 x2.