(* list_pred lifts a predicate on A and B to a predicate on list A and list B.  It is useful for reasoning about fold, map, etc. *)
Inductive list_pred(A B : Set)(pred : A -> B -> Prop) : list A -> list B -> Prop :=
| list_pred_nil : 
    list_pred pred nil nil
| list_pred_cons : 
    forall a1 a2 ls1 ls2,
      pred a1 a2 ->
      list_pred pred ls1 ls2 ->
      list_pred pred (a1 :: ls1) (a2 :: ls2).(* list_pred lifts a predicate on A and B to a predicate on list A and list B.  It is useful for reasoning about fold, map, etc. *)
Inductive list_pred(A B : Set)(pred : A -> B -> Prop) : list A -> list B -> Prop :=
| list_pred_nil : 
    list_pred pred nil nil
| list_pred_cons : 
    forall a1 a2 ls1 ls2,
      pred a1 a2 ->
      list_pred pred ls1 ls2 ->
      list_pred pred (a1 :: ls1) (a2 :: ls2).(* list_pred lifts a predicate on A and B to a predicate on list A and list B.  It is useful for reasoning about fold, map, etc. *)
Inductive list_pred(A B : Set)(pred : A -> B -> Prop) : list A -> list B -> Prop :=
| list_pred_nil : 
    list_pred pred nil nil
| list_pred_cons : 
    forall a1 a2 ls1 ls2,
      pred a1 a2 ->
      list_pred pred ls1 ls2 ->
      list_pred pred (a1 :: ls1) (a2 :: ls2).

Theorem fst_split_app_eq : forall (A B : Type)(ls1 ls2 : list (A * B)), fst (split (ls1 ++ ls2)) = fst (split ls1) ++ fst (split ls2).