(* 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 NoDup_map : forall (A B : Type)(f : A -> B)(ls : list A), NoDup (map f ls) -> (NoDup ls /\ (forall b1 b2, In b1 ls -> In b2 ls -> f b1 = f b2 -> b1 = b2)).