Inductive NoDup_gen : list A -> Prop :=
  | NoDup_gen_nil : NoDup_gen nil
  | NoDup_gen_cons : 
      forall (a : A)(ls : list A),
        (~In_gen ea a ls) -> 
        NoDup_gen ls ->
        NoDup_gen (a :: ls).Inductive NoDup_gen : list A -> Prop :=
  | NoDup_gen_nil : NoDup_gen nil
  | NoDup_gen_cons : 
      forall (a : A)(ls : list A),
        (~In_gen ea a ls) -> 
        NoDup_gen ls ->
        NoDup_gen (a :: ls).Inductive NoDup_gen : list A -> Prop :=
  | NoDup_gen_nil : NoDup_gen nil
  | NoDup_gen_cons : 
      forall (a : A)(ls : list A),
        (~In_gen ea a ls) -> 
        NoDup_gen ls ->
        NoDup_gen (a :: ls).

(* Specifications: *)
Theorem NoDup_gen_eq : forall (A : Type)(ls : list A), NoDup ls <-> NoDup_gen eq ls.
Theorem In_gen_map_iff : forall (l : list A) (y : B), (In_gen eb y (map f l) <-> (exists x : A, eb (f x) y /\ In_gen ea x l)).
Theorem map_NoDup_gen : forall (ls : list A), NoDup_gen ea ls -> NoDup_gen eb (map f ls).
Theorem In_gen_weaken : forall (A : Type)(e1 e2 : A -> A -> Prop) ls a, In_gen e1 a ls -> (forall a', e1 a a' -> e2 a a') -> In_gen e2 a ls.
Lemma flatten_NoDup_gen : forall (A : Set)(ls : list (list A)), NoDup_gen (fun a b => a <> nil /\ a = b) ls -> (forall x, In x ls -> NoDup x) -> (forall x1 x2, In x1 ls -> In x2 ls -> x1 <> x2 -> NoDup (x1 ++ x2)) -> NoDup (flatten ls).
Theorem NoDup_gen_weaken : forall (A : Type)(e1 e2 : A -> A -> Prop) ls, NoDup_gen e1 ls -> (forall a1 a2, e2 a1 a2 -> e1 a1 a2) -> NoDup_gen e2 ls.
Theorem In_gen_zip_fst : forall (A B : Set)(ea : A -> A -> Prop)(lsa : list A)(lsb : list B) a b, In_gen (fun a b => ea (fst a) (fst b)) (a, b) (zip lsa lsb) -> In_gen ea a lsa.
Theorem NoDup_gen_zip_fst : forall (A B : Set)(ea : A -> A -> Prop)(lsa : list A)(lsb : list B), NoDup_gen ea lsa -> NoDup_gen (fun a b => ea (fst a) (fst b)) (zip lsa lsb).