(**  Morphism property for unary and binary functions  **)
Definition morphism_1 aF rF := forall x, f (aF x) = rF (f x).Definition morphism_2 aOp rOp := forall x y, f (aOp x y) = rOp (f x) (f y).(**  Homomorphism property for unary and binary relations  **)
Definition homomorphism_1 (aP rP : _ -> Prop) := forall x, aP x -> rP (f x).Definition homomorphism_2 (aR rR : _ -> _ -> Prop) :=
  forall x y, aR x y -> rR (f x) (f y).(**  Stability property for unary and binary relations  **)
Definition monomorphism_1 (aP rP : _ -> sT) := forall x, rP (f x) = aP x.Definition monomorphism_2 (aR rR : _ -> _ -> sT) :=
  forall x y, rR (f x) (f y) = aR x y.Notation "{ 'morph' f : x / a >-> r }" :=
  (morphism_1 f (fun x => a) (fun x => r)) : type_scope.Notation "{ 'morph' f : x / a }" :=
  (morphism_1 f (fun x => a) (fun x => a)) : type_scope.Notation "{ 'morph' f : x y / a >-> r }" :=
  (morphism_2 f (fun x y => a) (fun x y => r)) : type_scope.Notation "{ 'morph' f : x y / a }" :=
  (morphism_2 f (fun x y => a) (fun x y => a)) : type_scope.Notation "{ 'homo' f : x / a >-> r }" :=
  (homomorphism_1 f (fun x => a) (fun x => r)) : type_scope.Notation "{ 'homo' f : x / a }" :=
  (homomorphism_1 f (fun x => a) (fun x => a)) : type_scope.Notation "{ 'homo' f : x y / a >-> r }" :=
  (homomorphism_2 f (fun x y => a) (fun x y => r)) : type_scope.Notation "{ 'homo' f : x y / a }" :=
  (homomorphism_2 f (fun x y => a) (fun x y => a)) : type_scope.Notation "{ 'homo' f : x y /~ a }" :=
  (homomorphism_2 f (fun y x => a) (fun x y => a)) : type_scope.Notation "{ 'mono' f : x / a >-> r }" :=
  (monomorphism_1 f (fun x => a) (fun x => r)) : type_scope.Notation "{ 'mono' f : x / a }" :=
  (monomorphism_1 f (fun x => a) (fun x => a)) : type_scope.Notation "{ 'mono' f : x y / a >-> r }" :=
  (monomorphism_2 f (fun x y => a) (fun x y => r)) : type_scope.Notation "{ 'mono' f : x y / a }" :=
  (monomorphism_2 f (fun x y => a) (fun x y => a)) : type_scope.Notation "{ 'mono' f : x y /~ a }" :=
  (monomorphism_2 f (fun y x => a) (fun x y => a)) : type_scope.Definition injective := forall x1 x2, f x1 = f x2 -> x1 = x2.Definition cancel g := forall x, g (f x) = x.Definition pcancel g := forall x, g (f x) = Some x.Definition ocancel (g : aT -> option rT) h := forall x, oapp h x (g x) = x.

(* Specifications: *)
Lemma can_pcan g : cancel g -> pcancel (fun y => Some (g y)).
Lemma pcan_inj g : pcancel g -> injective.
Lemma can_inj g : cancel g -> injective.
Lemma canLR g x y : cancel g -> x = f y -> g x = y.
Lemma canRL g x y : cancel g -> f x = y -> x = g y.
Lemma Some_inj {T : nonPropType} : injective (@Some T).
Lemma of_voidK T : pcancel (of_void T) [fun _ => None].
Lemma esymK T x y : cancel (@esym T x y) (@esym T y x).
Lemma etrans_id T x y (eqxy : x = y :> T) : etrans (erefl x) eqxy = eqxy.
Lemma inj_id : injective (@id A).
Lemma inj_can_sym f' : cancel f f' -> injective f' -> cancel f' f.
Lemma inj_comp : injective f -> injective h -> injective (f \o h).
Lemma inj_compr : injective (f \o h) -> injective h.
Lemma can_comp f' h' : cancel f f' -> cancel h h' -> cancel (f \o h) (h' \o f').
Lemma pcan_pcomp f' h' : pcancel f f' -> pcancel h h' -> pcancel (f \o h) (pcomp h' f').
Lemma ocan_comp [fo : B -> option A] [ho : C -> option B] [f' : A -> B] [h' : B -> C] : ocancel fo f' -> ocancel ho h' -> ocancel (obind fo \o ho) (h' \o f').
Lemma eq_inj : injective f -> f =1 g -> injective g.
Lemma eq_can f' g' : cancel f f' -> f =1 g -> f' =1 g' -> cancel g g'.
Lemma inj_can_eq f' : cancel f f' -> injective f' -> cancel g f' -> f =1 g.