(** We use an extern hint to help unification. *)

#[global]
Hint Extern 4 (subrelation (@forall_relation ?A ?B ?R) (@forall_relation _ _ ?S)) =>
  apply (@forall_subrelation A B R S) ; intro : typeclass_instances.Class Proper (R : relation A) (m : A) : Prop :=
    proper_prf : R m m.Class Proper (R : relation A) (m : A) : Prop :=
    proper_prf : R m m.(** Every element in the carrier of a reflexive relation is a morphism
   for this relation.  We use a proxy class for this case which is used
   internally to discharge reflexivity constraints.  The [Reflexive]
   instance will almost always be used, but it won't apply in general to
   any kind of [Proper (A -> B) _ _] goal, making proof-search much
   slower. A cleaner solution would be to be able to set different
   priorities in different hint bases and select a particular hint
   database for resolution of a type class constraint. *)

  Class ProperProxy (R : relation A) (m : A) : Prop :=
    proper_proxy : R m m.(** Every element in the carrier of a reflexive relation is a morphism
   for this relation.  We use a proxy class for this case which is used
   internally to discharge reflexivity constraints.  The [Reflexive]
   instance will almost always be used, but it won't apply in general to
   any kind of [Proper (A -> B) _ _] goal, making proof-search much
   slower. A cleaner solution would be to be able to set different
   priorities in different hint bases and select a particular hint
   database for resolution of a type class constraint. *)

  Class ProperProxy (R : relation A) (m : A) : Prop :=
    proper_proxy : R m m.Class ReflexiveProxy (R : relation A) : Prop :=
    reflexive_proxy : forall x, R x x.Class ReflexiveProxy (R : relation A) : Prop :=
    reflexive_proxy : forall x, R x x.

(* Specifications: *)
Lemma eq_proper_proxy (x : A) : ProperProxy (@eq A) x.
Lemma reflexive_proper `{ReflexiveProxy R} (x : A) : Proper R x.
Lemma reflexive_proper_proxy `(ReflexiveProxy R) (x : A) : ProperProxy R x.
Lemma proper_proper_proxy x `(Proper R x) : ProperProxy R x.
Lemma reflexive_reflexive_proxy `(Reflexive A R) : ReflexiveProxy R.