(************************************************************************)
(*         *      The Rocq Prover / The Rocq Development Team           *)
(*  v      *         Copyright INRIA, CNRS and contributors             *)
(* <O___,, * (see version control and CREDITS file for authors & dates) *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
(** * Typeclass-based morphism definition and standard, minimal instances  Author: Matthieu Sozeau Institution: LRI, CNRS UMR 8623 - University Paris Sud *)
Require Export Corelib.Classes.RelationClasses.
Generalizable Variables A eqA B C D R RA RB RC m f x y.
Local Obligation Tactic := try solve [ simpl_relation ].
(** * Morphisms.  We now turn to the definition of [Proper] and declare standard instances. These will be used by the [setoid_rewrite] tactic later. *)
(** A morphism for a relation [R] is a proper element of the relation. The relation [R] will be instantiated by [respectful] and [A] by an arrow type for usual morphisms. *)
Section Proper.
Let U := Type.
Context {A B : U}.
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.
Class ReflexiveProxy (R : relation A) : Prop :=
reflexive_proxy : forall x, R x x.

(* Specifications: *)
Lemma eq_proper_proxy (x : A) : ProperProxy (@eq A) x.
Global Instance proper_subrelation_proper :
Proper (subrelation ++> eq ==> impl) (@Proper A).