(** Transitivity and decomposition can be expressed in terms of [rel_compose] in the following way. *)
Global Instance rel_compose_rcompose {A B C} (RAB : rel A B) (RBC : rel B C) :
RCompose RAB RBC (rel_compose RAB RBC).
Global Instance rel_compose_rdecompose {A B C} (RAB : rel A B) (RBC : rel B C) :
RDecompose RAB RBC (rel_compose RAB RBC).
Global Instance rcompose_subrel `(RCompose) :
Related (rel_compose RAB RBC) RAC subrel.
Global Instance rdecompose_subrel `(RDecompose) :
Related RAC (rel_compose RAB RBC) subrel.
(** ** Pulling a relation along functions *)
Definition rel_pull {A B A' B'} f g (R: rel A' B'): rel A B :=
fun x y => R (f x) (g y).
(** We use the following notation. Left associativity would make more sense but we have to match [Coq.Classes.RelationPairs]. *)
Notation "R @@ ( f , g )" := (rel_pull f g R)
(at level 30, right associativity) : rel_scope.
Notation "R @@ f" := (rel_pull f f R)
(at level 30, right associativity) : rel_scope.
Notation "R @@ ( f )" := (rel_pull f f R)
(at level 30, right associativity) : rel_scope.
Global Instance rel_pull_subrel {A B A' B'} (f: A -> A') (g: B -> B'):
Monotonic (rel_pull f g) (subrel ++> subrel).
Global Instance rel_pull_subrel_params:
Params (@rel_pull) 3.
(** In the restricted case where [f = g], [rel_pull] preserves many properties of the underlying relation. *)

(* Specifications: *)
Lemma rel_pull_refl {A B} (f: A -> B) (R: rel B B):
Reflexive R ->
Reflexive (R @@ f).