(** This module defines the commutative_ring record type which represents algebraic commutative rings and provides a collection of axioms and theorems 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 Commutative_Ring.
(** Represents algebraic commutative rings. *)
Structure Commutative_Ring : Type := commutative_ring {
(** Represents the set of ring elements. *)
E : Set;
(** Represents 0 - the additive identity. *)
E_0 : E;
(** Represents 1 - the multiplicative identity. *)
E_1 : E;
(** Represents addition. *)
sum : E -> E -> E;
(** Represents multiplication. *)
prod : E -> E -> E;
(** Asserts that 0 /= 1. *)
distinct_0_1: E_0 <> E_1;
(** Asserts that addition is associative. *)
sum_is_assoc : Monoid.is_assoc E sum;
(** Asserts that addition is commutative. *)
sum_is_comm : Abelian_Group.is_comm E sum;
(** Asserts that 0 is the left identity element. *)
sum_id_l : Monoid.is_id_l E sum E_0;
(** Asserts that every element has an additive inverse. *)
sum_inv_l_ex : forall x : E, exists y : E, sum y x = E_0;
(** Asserts that multiplication is associative. *)
prod_is_assoc : Monoid.is_assoc E prod;
(** Asserts that multiplication is commutative. *)
prod_is_comm : Abelian_Group.is_comm E prod;
(** Asserts that 1 is the left identity element. *)
prod_id_l : Monoid.is_id_l E prod E_1;
(** Asserts that multiplication is left distributive over addition. *)
prod_sum_distrib_l : Ring.is_distrib_l E prod sum
}.
(** Enable implicit arguments for commutative ring properties. *)
Arguments E_0 {c}.
Arguments E_1 {c}.
Arguments sum {c} x y.
Arguments prod {c} x y.
Arguments distinct_0_1 {c} _.
Arguments sum_is_assoc {c} x y z.
Arguments sum_is_comm {c} x y.
Arguments sum_id_l {c} x.
Arguments sum_inv_l_ex {c} x.
Arguments prod_is_assoc {c} x y z.
Arguments prod_id_l {c} x.
Arguments prod_sum_distrib_l {c} x y z.
Arguments prod_is_comm {c} x y.
(** Define notations for ring properties. *)
Notation "0" := E_0 : commutative_ring_scope.
Notation "1" := E_1 : commutative_ring_scope.
Notation "x + y" := (sum x y) (at level 50, left associativity) : commutative_ring_scope.
Notation "{+}" := sum : commutative_ring_scope.
Notation "x # y" := (prod x y) (at level 50, left associativity) : commutative_ring_scope.
Notation "{#}" := prod : commutative_ring_scope.
Open Scope commutative_ring_scope.
Section Theorems.
(** Represents an arbitrary commutative ring.  Note: we use Variable rather than Parameter to ensure that the following theorems are generalized w.r.t r. *)
Variable r : Commutative_Ring.
(** Represents the set of group elements.  Note: We use Let to define E as a local abbreviation. *)
Let E := E r.
(** Accepts one ring element, x, and asserts that x is the left identity element. *)
Definition sum_is_id_l := Monoid.is_id_l E {+}.
(** Accepts one ring element, x, and asserts that x is the right identity element. *)
Definition sum_is_id_r := Monoid.is_id_r E {+}.
(** Accepts one ring element, x, and asserts that x is the identity element. *)
Definition sum_is_id := Monoid.is_id E {+}.
(** Accepts one ring element, x, and asserts that x is the left identity element. *)
Definition prod_is_id_l := Monoid.is_id_l E {#}.
(** Accepts one ring element, x, and asserts that x is the right identity element. *)
Definition prod_is_id_r := Monoid.is_id_r E {#}.
(** Accepts one ring element, x, and asserts that x is the identity element. *)
Definition prod_is_id := Monoid.is_id E {#}.

(** Proves that 1 is the right identity element. *)
Theorem prod_id_r
:  prod_is_id_r 1.