(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.(** Represents algebraic groups. *)
Structure Group : Type := group {

  (** Represents the set of group elements. *)
  E: Set;

  (** Represents the identity element. *)
  E_0: E;

  (** Represents the group operation. *)
  op: E -> E -> E;

  (** Asserts that the group operator is associative. *)
  op_is_assoc : Monoid.is_assoc E op;

  (** Asserts that E_0 is the left identity element. *)
  op_id_l : Monoid.is_id_l E op E_0;

  (** Asserts that E_0 is the right identity element. *)
  op_id_r : Monoid.is_id_r E op E_0;

  (**
    Asserts that every group element has a
    left inverse.
  *)
  op_inv_l_ex : forall x : E, exists y : E, Monoid.is_inv_l E op E_0 (conj op_id_l op_id_r) x y;

  (**
    Asserts that every group element has a
    right inverse.
  *)
  op_inv_r_ex : forall x : E, exists y : E, Monoid.is_inv_r E op E_0 (conj op_id_l op_id_r) x y
}.Notation "0" := (Group.E_0) : group_scope.Notation "x + y" := (Group.op x y) (at level 50, left associativity) : group_scope.Notation "{+}" := (Group.op) : group_scope.(**
  Accepts one group element, x, and asserts
  that x is the left identity element.
*)
Definition op_is_id_l := Monoid.op_is_id_l op_monoid.(**
  Accepts one group element, x, and asserts
  that x is the right identity element.
*)
Definition op_is_id_r := Monoid.op_is_id_r op_monoid.(**
  Accepts one group element, x, and asserts
  that x is the identity element.
*)
Definition op_is_id := Monoid.op_is_id op_monoid.

(* Specifications: *)
Theorem op_id : op_is_id 0.