Proof
conj op_inv_0
(fun x H => eq_sym (op_inv_0_eq_0 x H)).
(** Every monoid has a subset of elements that possess inverses. This can be seen by noting that, by definition, every monoid has an identity element (this is what distinguishes a monoid from a semigroup) and the identity element is its own inverse. The following theorems explore the behavior of those elements that possess inverses. They will prove especially ueseful when we consider groups where every element possess an inverse. *)
(** Accepts two arguments: x; and H, a proof that x has an inverse; and returns x's inverse, y, along with a proof that y is x's inverse. *)
Definition op_neg_strong
:  forall x : M, has_inv x -> { y | op_is_inv x y }
:= fun x H
=> constructive_definite_description (op_is_inv x)
(ex_ind
(fun y (H0 : op_is_inv x y)
=> ex_intro
(fun y => op_is_inv x y /\ forall z, op_is_inv x z -> y = z)
y
(conj H0 (fun z H1 => eq_sym (op_inv_uniq x y z H0 H1))))
H).
(** Accepts two arguments: x; and H, a proof that x has an inverse. and returns x's inverse. *)
Definition op_neg
:  forall x : M, has_inv x -> M
:= fun x H => proj1_sig (op_neg_strong x H).
Notation "{-}" := (op_neg) : monoid_scope.

(* Specifications: *)
(** Proves that, forall x and H, where H is a proof that x has an inverse, `op_neg x H` is x's inverse. *)
Theorem op_neg_def
:  forall (x : M) (H : has_inv x), op_is_inv x ({-} x H).