open import 1Lab.Prelude hiding (_*_ ; _+_)

open import Algebra.Semigroup
open import Algebra.Group.Ab
open import Algebra.Monoid
open import Algebra.Group

open import Cat.Displayed.Univalence.Thin
open import Cat.Base

open import Data.Int.Properties
open import Data.Int.Base

import Algebra.Monoid.Reasoning as Mon

import Cat.Reasoning

module Algebra.Ring where


# Ringsπ

The ring is one of the basic objects of study in algebra, which abstracts the best bits of the common algebraic structures: The integers the rationals the reals and the complex numbers are all rings, as are the collections of polynomials with coefficients in any of those. Less familiar examples of rings include square matrices (with values in a ring) and the integral cohomology ring of a topological space: that these are so far from being βnumber-likeβ indicates the incredible generality of rings.

A ring is an abelian group (which we call the additive group of together with the data of a monoid on (the multiplicative monoid), where the multiplication of the monoid distributes over the addition. Weβll see why this compatibility condition is required afterwards. Check out what it means for a triple to be a ring structure on a type:

record is-ring {β} {R : Type β} (1r : R) (_*_ _+_ : R β R β R) : Type β where
no-eta-equality
field
*-monoid : is-monoid 1r _*_
+-group  : is-abelian-group _+_
*-distribl : β {x y z} β x * (y + z) β‘ (x * y) + (x * z)
*-distribr : β {x y z} β (y + z) * x β‘ (y * x) + (z * x)

  open is-monoid *-monoid
renaming ( idl to *-idl
; idr to *-idr
; associative to *-associative
)
hiding (has-is-set ; magma-hlevel ; underlying-set)
public

open is-abelian-group +-group
renaming ( _β_ to _-_
; inverse to -_
; 1g to 0r
; inversel to +-invl
; inverser to +-invr
; associative to +-associative
; idl to +-idl
; idr to +-idr
; commutes to +-commutes
)
public

additive-group : Ξ£ (Set β) (Ξ» x β Group-on β x β)
β£ additive-group .fst β£                    = R
additive-group .fst .is-tr                 = is-abelian-group.has-is-set +-group
additive-group .snd .Group-on._β_          = _+_
additive-group .snd .Group-on.has-is-group = is-abelian-group.has-is-group +-group

group : Abelian-group β
β£ group .fst β£                         = R
group .fst .is-tr                      = is-abelian-group.has-is-set +-group
group .snd .Abelian-group-on._*_       = _+_
group .snd .Abelian-group-on.has-is-ab = +-group

multiplicative-monoid : Monoid β
multiplicative-monoid .fst = R
multiplicative-monoid .snd = record { has-is-monoid = *-monoid }

module m = Mon multiplicative-monoid
module a = Abelian-group-on record { has-is-ab = +-group }
hiding (_*_ ; 1g ; _β»ΒΉ)

record Ring-on {β} (R : Type β) : Type β where
field
1r : R
_*_ _+_ : R β R β R
has-is-ring : is-ring 1r _*_ _+_

open is-ring has-is-ring public
infixl 25 _*_
infixl 20 _+_

instance
H-Level-is-ring
: β {β} {R : Type β} {1r : R} {_*_ _+_ : R β R β R} {n}
β H-Level (is-ring 1r _*_ _+_) (suc n)
H-Level-is-ring {1r = 1r} {_*_} {_+_} =
prop-instance {T = is-ring 1r _*_ _+_} \$ Ξ» where
x y i .*-monoid   β hlevel 1 (x .*-monoid) (y .*-monoid) i
x y i .+-group    β hlevel 1 (x .+-group) (y .+-group) i
x y i .*-distribl β x .+-group .is-abelian-group.has-is-set _ _ (x .*-distribl) (y .*-distribl) i
x y i .*-distribr β x .+-group .is-abelian-group.has-is-set _ _ (x .*-distribr) (y .*-distribr) i
where open is-ring


There is a natural notion of ring homomorphism, which we get by smashing together that of a monoid homomorphism (for the multiplicative part) and of group homomorphism; Every map of rings has an underlying map of groups which preserves the addition operation, and it must also preserve the multiplication. This encodes the view of a ring as an βabelian group with a monoid structureβ.

record is-ring-hom
{β β'} {A : Type β} {B : Type β'} (R : Ring-on A) (S : Ring-on B)
(f : A β B)
: Type (β β β') where
private
module A = Ring-on R
module B = Ring-on S

field
pres-id : f A.1r β‘ B.1r
pres-+  : β x y β f (x A.+ y) β‘ f x B.+ f y
pres-*  : β x y β f (x A.* y) β‘ f x B.* f y

  ring-homβgroup-hom : is-group-hom (A.additive-group .snd) (B.additive-group .snd) f
ring-homβgroup-hom = record { pres-β = pres-+ }

module gh = is-group-hom ring-homβgroup-hom renaming (pres-id to pres-0 ; pres-inv to pres-neg)
open gh using (pres-0 ; pres-neg ; pres-diff) public

private unquoteDecl eqv = declare-record-iso eqv (quote is-ring-hom)

module _ {β β'} {A : Type β} {B : Type β'} {R : Ring-on A} {S : Ring-on B} where
open Ring-on R using (magma-hlevel)
open Ring-on S using (magma-hlevel)

instance abstract
H-Level-ring-hom : β {f n} β H-Level (is-ring-hom R S f) (suc n)
H-Level-ring-hom = prop-instance Ξ» x y β Isoβis-hlevel 1 eqv (hlevel 1) x y

open is-ring-hom


It follows, by standard equational nonsense, that rings and ring homomorphisms form a precategory β for instance, we have

Ring-structure : β β β Thin-structure β Ring-on
Ring-structure β .is-hom f x y = el! (is-ring-hom x y f)
Ring-structure β .id-is-hom .pres-id = refl
Ring-structure β .id-is-hom .pres-+ x y = refl
Ring-structure β .id-is-hom .pres-* x y = refl
Ring-structure β .β-is-hom f g Ξ± Ξ² .pres-id = ap f (Ξ² .pres-id) β Ξ± .pres-id
Ring-structure β .β-is-hom f g Ξ± Ξ² .pres-+ x y = ap f (Ξ² .pres-+ x y) β Ξ± .pres-+ _ _
Ring-structure β .β-is-hom f g Ξ± Ξ² .pres-* x y = ap f (Ξ² .pres-* x y) β Ξ± .pres-* _ _
Ring-structure β .id-hom-unique Ξ± Ξ² i .Ring-on.1r = Ξ± .pres-id i
Ring-structure β .id-hom-unique Ξ± Ξ² i .Ring-on._*_ x y = Ξ± .pres-* x y i
Ring-structure β .id-hom-unique Ξ± Ξ² i .Ring-on._+_ x y = Ξ± .pres-+ x y i
Ring-structure β .id-hom-unique {s = s} {t} Ξ± Ξ² i .Ring-on.has-is-ring =
is-propβpathp
(Ξ» i β hlevel {T = is-ring (Ξ± .pres-id i)
(Ξ» x y β Ξ± .pres-* x y i) (Ξ» x y β Ξ± .pres-+ x y i)} 1)
(s .Ring-on.has-is-ring) (t .Ring-on.has-is-ring) i

Rings : β β β Precategory (lsuc β) β
Rings _ = Structured-objects (Ring-structure _)
module Rings {β} = Cat.Reasoning (Rings β)

Ring : β β β Type (lsuc β)
Ring β = Rings.Ob


## In componentsπ

We give a more elementary description of rings, which is suitable for constructing values of the record type Ring above. This re-expresses the data included in the definition of a ring with the least amount of redundancy possible, in the most direct terms possible: A ring is a set, equipped with two binary operations and such that distributes over on either side; is an abelian group; and is a monoid.

record make-ring {β} (R : Type β) : Type β where
no-eta-equality
field
ring-is-set : is-set R

-- R is an abelian group:
0R      : R
_+_     : R β R β R
-_      : R β R
+-idl   : β x β 0R + x β‘ x
+-invr  : β x β x + (- x) β‘ 0R
+-assoc : β x y z β x + (y + z) β‘ (x + y) + z
+-comm  : β x y β x + y β‘ y + x

-- R is a commutative monoid:
1R      : R
_*_     : R β R β R
*-idl   : β x β 1R * x β‘ x
*-idr   : β x β x * 1R β‘ x
*-assoc : β x y z β x * (y * z) β‘ (x * y) * z

-- Multiplication is bilinear:
*-distribl : β x y z β x * (y + z) β‘ (x * y) + (x * z)
*-distribr : β x y z β (y + z) * x β‘ (y * x) + (z * x)

  to-ring-on : Ring-on R
to-ring-on = ring where
open is-ring hiding (-_ ; +-invr ; +-invl ; *-distribl ; *-distribr ; *-idl ; *-idr ; +-idl ; +-idr)
open is-monoid

-- All in copatterns to prevent the unfolding from exploding on you
ring : Ring-on R
ring .Ring-on.1r = 1R
ring .Ring-on._*_ = _*_
ring .Ring-on._+_ = _+_
ring .Ring-on.has-is-ring .*-monoid .has-is-semigroup .is-semigroup.has-is-magma = record { has-is-set = ring-is-set }
ring .Ring-on.has-is-ring .*-monoid .has-is-semigroup .is-semigroup.associative = *-assoc _ _ _
ring .Ring-on.has-is-ring .*-monoid .idl = *-idl _
ring .Ring-on.has-is-ring .*-monoid .idr = *-idr _
ring .Ring-on.has-is-ring .+-group .is-abelian-group.has-is-group .is-group.unit = 0R
ring .Ring-on.has-is-ring .+-group .is-abelian-group.has-is-group .is-group.has-is-monoid .has-is-semigroup .has-is-magma = record { has-is-set = ring-is-set }
ring .Ring-on.has-is-ring .+-group .is-abelian-group.has-is-group .is-group.has-is-monoid .has-is-semigroup .associative = +-assoc _ _ _
ring .Ring-on.has-is-ring .+-group .is-abelian-group.has-is-group .is-group.has-is-monoid .idl = +-idl _
ring .Ring-on.has-is-ring .+-group .is-abelian-group.has-is-group .is-group.has-is-monoid .idr = +-comm _ _ β +-idl _
ring .Ring-on.has-is-ring .+-group .is-abelian-group.has-is-group .is-group.inverse = -_
ring .Ring-on.has-is-ring .+-group .is-abelian-group.has-is-group .is-group.inversel = +-comm _ _ β +-invr _
ring .Ring-on.has-is-ring .+-group .is-abelian-group.has-is-group .is-group.inverser = +-invr _
ring .Ring-on.has-is-ring .+-group .is-abelian-group.commutes = +-comm _ _
ring .Ring-on.has-is-ring .is-ring.*-distribl = *-distribl _ _ _
ring .Ring-on.has-is-ring .is-ring.*-distribr = *-distribr _ _ _

to-ring : Ring β
to-ring .fst = el R ring-is-set
to-ring .snd = to-ring-on

open make-ring using (to-ring ; to-ring-on) public


This data is missing (by design, actually!) one condition which we would expect: We exploit this to give our first example of a ring, the zero ring, which has carrier set the unit β the type with one object.

Despite the name, the zero ring is not the zero object in the category of rings: it is the terminal object. In the category of rings, the initial object is the ring which is very far (infinitely far!) from having a single element. Itβs called the βzero ringβ because it has one element which must be the additive identity, hence we call it But itβs also the multiplicative identity, so we might also call the ring the One Ring, which would be objectively cooler.

Zero-ring : Ring lzero
Zero-ring = to-ring {R = β€} Ξ» where
.make-ring.ring-is-set _ _ _ _ _ _ β tt
.make-ring.0R                      β tt
.make-ring._+_ _ _                 β tt
.make-ring.-_  _                   β tt
.make-ring.+-idl  _ _              β tt
.make-ring.+-invr _ _              β tt
.make-ring.+-assoc _ _ _ _         β tt
.make-ring.+-comm _ _ _            β tt
.make-ring.1R                      β tt
.make-ring._*_ _ _                 β tt
.make-ring.*-idl _ _               β tt
.make-ring.*-idr _ _               β tt
.make-ring.*-assoc _ _ _ _         β tt
.make-ring.*-distribl _ _ _ _      β tt
.make-ring.*-distribr _ _ _ _      β tt


Rings, unlike other categories of algebraic structures (like that of groups or abelian groups), are structured enough to differentiate between the initial and terminal objects. As mentioned above, the initial object is the ring and the terminal ring is the zero ring. As for why this happens, consider that, since ring homomorphisms must preserve the unit1, it is impossible to have a ring homomorphism unless in

β€ : Ring lzero
β€ = to-ring {R = Int} Ξ» where
.make-ring.ring-is-set β hlevel 2
.make-ring.1R         β 1
.make-ring.0R         β 0
.make-ring._+_        β _+β€_
.make-ring.-_         β negβ€
.make-ring._*_        β _*β€_
.make-ring.+-idl      β +β€-zerol
.make-ring.+-invr     β +β€-invr
.make-ring.+-assoc    β +β€-assoc
.make-ring.+-comm     β +β€-commutative
.make-ring.*-idl      β *β€-onel
.make-ring.*-idr      β *β€-oner
.make-ring.*-assoc    β *β€-associative
.make-ring.*-distribl β *β€-distribl
.make-ring.*-distribr β *β€-distribr


1. being homomorphisms for the additive group, they automatically preserve zeroβ©οΈ