Section Type_with_equality.
Variable A : Type.
Variable eqA : A -> A -> Prop.
(** Being in a list modulo an equality relation over type [A]. *)
Inductive InA (x : A) : list A -> Prop :=
| InA_cons_hd : forall y l, eqA x y -> InA x (y :: l)
| InA_cons_tl : forall y l, InA x l -> InA x (y :: l).
Hint Constructors InA : core.
(** TODO: it would be nice to have a generic definition instead of the previous one. Having [InA = Exists eqA] raises too many compatibility issues. For now, we only state the equivalence: *)
(** An alternative definition of [InA]. *)
(** A list without redundancy modulo the equality over [A]. *)
Inductive NoDupA : list A -> Prop :=
| NoDupA_nil : NoDupA nil
| NoDupA_cons : forall x l, ~ InA x l -> NoDupA l -> NoDupA (x::l).
Hint Constructors NoDupA : core.
(** An alternative definition of [NoDupA] based on [ForallOrdPairs] *)
(** lists with same elements modulo [eqA] *)
Definition inclA l l' := forall x, InA x l -> InA x l'.
Definition equivlistA l l' := forall x, InA x l <-> InA x l'.
Global Instance eqlistA_equiv : Equivalence eqlistA.
(** Moreover, [eqlistA] implies [equivlistA]. A reverse result will be proved later for sorted list without duplicates. *)
Global Instance eqlistA_equivlistA : subrelation eqlistA equivlistA.
(** InA is compatible with eqA (for its first arg) and with equivlistA (and hence eqlistA) for its second arg *)
Global Instance InA_compat : Proper (eqA==>equivlistA==>iff) InA.
(** For compatibility, an immediate consequence of [InA_compat] *)
Hint Immediate InA_eqA : core.
Hint Resolve In_InA : core.
(** Some more facts about InA *)

Lemma InA_permute_heads x y z l :
InA x (y :: z :: l) <-> InA x (z :: y :: l).