(* An association list has unique keys if the keys appear only once *)
Inductive unique_key : list (A * B) -> Prop :=
  | unique_key_nil : unique_key nil
  | unique_key_cons :
      forall (a : A) (b : B) l,
      (forall b : B, ~ In (a, b) l) ->
      unique_key l -> unique_key ((a, b) :: l).(* An association list has unique keys if the keys appear only once *)
Inductive unique_key : list (A * B) -> Prop :=
  | unique_key_nil : unique_key nil
  | unique_key_cons :
      forall (a : A) (b : B) l,
      (forall b : B, ~ In (a, b) l) ->
      unique_key l -> unique_key ((a, b) :: l).(* An association list has unique keys if the keys appear only once *)
Inductive unique_key : list (A * B) -> Prop :=
  | unique_key_nil : unique_key nil
  | unique_key_cons :
      forall (a : A) (b : B) l,
      (forall b : B, ~ In (a, b) l) ->
      unique_key l -> unique_key ((a, b) :: l).

(* Specifications: *)
Theorem unique_key_inv : forall a l, unique_key (a :: l) -> unique_key l.
Theorem unique_key_in : forall (a : A) (b1 b2 : B) l, unique_key ((a, b1) :: l) -> ~ In (a, b2) l.
Theorem unique_key_in_inv : forall a l1 l2 l, unique_key l -> In (a, l1) l -> In (a, l2) l -> l1 = l2.
Theorem unique_key_perm : forall l1 l2, permutation l1 l2 -> unique_key l1 -> unique_key l2.
Theorem unique_key_app : forall l1 l2, unique_key l1 -> unique_key l2 -> (forall a b c, In (a, b) l1 -> In (a, c) l2 -> False) -> unique_key (l1 ++ l2).
Theorem unique_key_ulist : forall l : list (A * B), unique_key l -> ulist (map (fst (B:=_)) l).
Theorem ulist_unique_key : forall l : list (A * B), ulist (map (fst (B:=_)) l) -> unique_key l.
Theorem unique_key_map : forall (A B C D : Type) l (f : A * B -> C * D), unique_key l -> (forall a b, fst (f a) = fst (f b) -> fst a = fst b) -> unique_key (map f l).