(**
  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 "{-}" := (Monoid.op_neg _) : monoid_scope.

(* Specifications: *)
Theorem op_inv_closed : forall (x : M) (H : has_inv x) (y : M) (H0 : has_inv y), has_inv (x + y).