#[global]
Hint Resolve eq_refl eq_trans : core.
End IsEqOrig.
(** * Types with decidable equality *)
Module Type HasEqDec (Import E:Eq').
Parameter eq_dec : forall x y : t, { x==y } + { ~ x==y }.
End HasEqDec.
(** * Boolean Equality *)
(** Having [eq_dec] is the same as having a boolean equality plus a correctness proof. *)
Module Type HasEqb (Import T:Typ).
Parameter Inline eqb : t -> t -> bool.
End HasEqb.
Module Type EqbSpec (T:Typ)(X:HasEq T)(Y:HasEqb T).
Parameter eqb_eq : forall x y, Y.eqb x y = true <-> X.eq x y.
End EqbSpec.
Module Type EqbNotation (T:Typ)(E:HasEqb T).
Infix "=?" := E.eqb (at level 70, no associativity).
End EqbNotation.
Module Type HasEqBool (E:Eq) := HasEqb E <+ EqbSpec E E.
(** From these basic blocks, we can build many combinations of static standalone module types. *)
Module Type EqualityType := Eq <+ IsEq.
Module Type EqualityTypeOrig := Eq <+ IsEqOrig.
Module Type EqualityTypeBoth <: EqualityType <: EqualityTypeOrig
:= Eq <+ IsEq <+ IsEqOrig.
Module Type DecidableType <: EqualityType
:= Eq <+ IsEq <+ HasEqDec.
Module Type DecidableTypeOrig <: EqualityTypeOrig
:= Eq <+ IsEqOrig <+ HasEqDec.
Module Type DecidableTypeBoth <: DecidableType <: DecidableTypeOrig
:= EqualityTypeBoth <+ HasEqDec.
Module Type BooleanEqualityType <: EqualityType
:= Eq <+ IsEq <+ HasEqBool.
Module Type BooleanDecidableType <: DecidableType <: BooleanEqualityType
:= Eq <+ IsEq <+ HasEqDec <+ HasEqBool.
Module Type DecidableTypeFull <: DecidableTypeBoth <: BooleanDecidableType
:= Eq <+ IsEq <+ IsEqOrig <+ HasEqDec <+ HasEqBool.
(** Same, with notation for [eq] *)
Module Type EqualityType' := EqualityType <+ EqNotation.
Module Type EqualityTypeOrig' := EqualityTypeOrig <+ EqNotation.
Module Type EqualityTypeBoth' := EqualityTypeBoth <+ EqNotation.
Module Type DecidableType' := DecidableType <+ EqNotation.
Module Type DecidableTypeOrig' := DecidableTypeOrig <+ EqNotation.
Module Type DecidableTypeBoth' := DecidableTypeBoth <+ EqNotation.
Module Type BooleanEqualityType' :=
BooleanEqualityType <+ EqNotation <+ EqbNotation.
Module Type BooleanDecidableType' :=
BooleanDecidableType <+ EqNotation <+ EqbNotation.
Module Type DecidableTypeFull' := DecidableTypeFull <+ EqNotation.
(** * Compatibility wrapper from/to the old version of [EqualityType] and [DecidableType] *)
Module BackportEq (E:Eq)(F:IsEq E) <: IsEqOrig E.
Definition eq_refl := @Equivalence_Reflexive _ _ F.eq_equiv.
Definition eq_sym := @Equivalence_Symmetric _ _ F.eq_equiv.
Definition eq_trans := @Equivalence_Transitive _ _ F.eq_equiv.
End BackportEq.
Module UpdateEq (E:Eq)(F:IsEqOrig E) <: IsEq E.
#[global]
Instance eq_equiv : Equivalence E.eq.
End HasEqDec2Bool.
Module HasEqBool2Dec (E:Eq)(F:HasEqBool E) <: HasEqDec E.

(* Specifications: *)
Lemma eq_dec : forall x y, {E.eq x y}+{~E.eq x y}.
(** Alternative specification of [eqb] based on [reflect]. *)
Lemma eqb_spec x y : reflect (x==y) (x =? y).
(** Basic equality laws for [eqb] *)
Lemma eqb_refl x : (x =? x) = true.
Lemma eqb_sym x y : (x =? y) = (y =? x).
End BoolEqualityFacts.