{-# OPTIONS --without-K --rewriting --overlapping-instances #-}

open import lib.Basics
open import lib.types.Group
open import lib.groups.Homomorphism
open import lib.groups.TensorProduct

module lib.types.CRing where

-- 1-approximation of commutative rings without higher coherence conditions.
record CRingStructure {i} (El : Type i)
  : Type i where
  constructor ring-structure
  field
    add-group-struct : GroupStructure El

  open GroupStructure add-group-struct

  zero : El
  zero = ident

  add : El  El  El
  add = comp

  neg : El  El
  neg = inv

  field
    add-comm    :  a b  add a b == add b a
    one         : El
    mult        : El  El  El
    mult-unit-l :  a  mult one a == a
    mult-assoc  :  a b c  mult (mult a b) c == mult a (mult b c)
    mult-comm   :  a b  mult a b == mult b a
    distr-l     :  a b c  mult (add a b) c == add (mult a c) (mult b c)

  private
    infix 80 _⊕_
    _⊕_ = add
    infix 90 _⊗_
    _⊗_ = mult

  add-assoc :  a b c  (a  b)  c == a  (b  c)
  add-assoc = assoc

  abstract
    mult-unit-r :  a  a  one == a
    mult-unit-r a =
      a  one  =⟨ mult-comm a one 
      one  a  =⟨ mult-unit-l a 
      a        =∎

    distr-r :  a b c  a  (b  c) == a  b  a  c
    distr-r a b c =
      a  (b  c)    =⟨ mult-comm a (add b c) 
      (b  c)  a    =⟨ distr-l b c a 
      b  a  c  a  =⟨ (mult-comm b a) |in-ctx  x  add x (mult c a)) 
      a  b  c  a  =⟨ (mult-comm c a) |in-ctx (add (mult a b)) 
      a  b  a  c  =∎

    mult-zero-l :  a  zero  a == zero
    mult-zero-l a =
      cancel-l (zero  a) $
        zero  a  zero  a  =⟨ ! (distr-l zero zero a) 
        (zero  zero)  a    =⟨ unit-l zero |in-ctx  x  x  a) 
        zero  a             =⟨ ! (unit-r (zero  a)) 
        zero  a  zero      =∎

    mult-zero-r :  a  a  zero == zero
    mult-zero-r a =
      a  zero  =⟨ mult-comm a zero 
      zero  a  =⟨ mult-zero-l a 
      zero      =∎

record CRing i : Type (lsucc i) where
  constructor ring
  field
    El : Type i
    {{El-level}} : has-level 0 El
    ring-struct : CRingStructure El
  open CRingStructure ring-struct public

  add-group : Group i
  add-group = group El add-group-struct

  add-abgroup : AbGroup i
  add-abgroup = add-group , add-comm

  mult-hom : El  add-group →ᴳ add-group
  mult-hom g = group-hom (mult g) (distr-r g)

  mult-hom-zero : mult-hom zero == cst-hom
  mult-hom-zero = group-hom= (λ= mult-zero-l)

  private
    module R⊗R = TensorProduct add-abgroup add-abgroup
    module UP = R⊗R.UniversalProperty add-abgroup

    mult-bilinear-map : UP.BilinearMap
    mult-bilinear-map =
      record
      { bmap = mult
      ; linearity-l = distr-l
      ; linearity-r = distr-r
      }

  mult-hom' : R⊗R.grp →ᴳ add-group
  mult-hom' = UP.extend mult-bilinear-map

  mult-hom'-β :  a b  GroupHom.f mult-hom' (a R⊗R.⊗ b) == mult a b
  mult-hom'-β = UP.extend-β mult-bilinear-map

Ring₀ : Type (lsucc lzero)
Ring₀ = CRing lzero