Section Theorems.
(** Represents an arbitrary abelian group.  Note: we use Variable rather than Parameter to ensure that the following theorems are generalized w.r.t ag. *)
Variable g : Abelian_Group.
(** Represents the set of group elements.  Note: We use Let to define E as a local abbreviation. *)
Let E := E g.
(** Accepts one group element, x, and asserts that x is the left identity element. *)
Definition op_is_id_l := Monoid.is_id_l E {+}.
(** Accepts one group element, x, and asserts that x is the right identity element. *)
Definition op_is_id_r := Monoid.is_id_r E {+}.
(** Accepts one group element, x, and asserts that x is the identity element. *)
Definition op_is_id := Monoid.is_id E {+}.
Proof
fun x H y
=> H y
|| a = y @a by op_is_comm y x.
Proof
fun x H
=> conj H (op_is_id_lr x H).
Proof op_is_id_lr 0 op_id_l.
Proof conj op_id_l op_id_r.
(** Accepts two group elements, x and y, and asserts that y is x's left inverse. *)
Definition op_is_inv_l := Monoid.is_inv_l E {+} 0 op_id.
(** Accepts two group elements, x and y, and asserts that y is x's right inverse. *)
Definition op_is_inv_r := Monoid.is_inv_r E {+} 0 op_id.
(** Accepts two group elements, x and y, and asserts that y is x's inverse. *)
Definition op_is_inv := Monoid.is_inv E {+} 0 op_id.

(** Proves that every element has a right inverse. *)
Theorem op_inv_r_ex
:  forall x : E, exists y : E, op_is_inv_r x y.