(** This module defines the Group record type which can be used to represent algebraic groups and provides a collection of theorems and axioms describing them.  Copyright (C) 2018 Larry D. Lee Jr. <llee454@gmail.com>  This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. *)
Module Group.
(** 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
}.
(** Enable implicit arguments for group properties. *)
Arguments E_0 {g}.
Arguments op {g} x y.
Arguments op_is_assoc {g} x y z.
Arguments op_id_l {g} x.
Arguments op_id_r {g} x.
Arguments op_inv_l_ex {g} x.
Arguments op_inv_r_ex {g} x.
(** Define notations for group properties. *)
Notation "0" := E_0 : group_scope.
Notation "x + y" := (op x y) (at level 50, left associativity) : group_scope.
Notation "{+}" := op : group_scope.
Open Scope group_scope.
Section Theorems.
(** Represents an arbitrary group.  Note: we use Variable rather than Parameter to ensure that the following theorems are generalized w.r.t g. *)
Variable g : Group.
(** Represents the set of group elements. *)
Let E := E g.
(** Represents the monoid structure formed by op over E. *)
Definition op_monoid := Monoid.monoid E 0 {+} op_is_assoc op_id_l op_id_r.
(** 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.

(** Proves that 0 is the identity element. *)
Theorem op_id
:  op_is_id 0.