content: {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
  module Numeric.Ring.Rng
    ( RngRing(..)
    , rngRingHom
    , liftRngHom
    ) where
  
  import Numeric.Algebra
  import Prelude hiding ((+),(-),(*),(/),replicate,negate,subtract,fromIntegral)
  
  -- | The free Ring given a Rng obtained by adjoining Z, such that
  -- 
  -- > RngRing r = n*1 + r
  --
  -- This ring is commonly denoted r^.
  data RngRing r = RngRing !Integer r deriving (Show,Read)
  
  instance Abelian r => Additive (RngRing r) where
    RngRing n a + RngRing m b = RngRing (n + m) (a + b)
    sinnum1p n (RngRing m a) = RngRing ((1 + toInteger n) * m) (sinnum1p n a)
  
  instance Abelian r => Abelian (RngRing r)
  
  instance (Abelian r, Monoidal r) => LeftModule Natural (RngRing r) where
    n .* RngRing m a = RngRing (toInteger n * m) (sinnum n a)
  
  instance (Abelian r, Monoidal r) => RightModule Natural (RngRing r) where
    RngRing m a *. n = RngRing (toInteger n * m) (sinnum n a)
  
  instance (Abelian r, Monoidal r) => Monoidal (RngRing r) where
    zero = RngRing 0 zero
    sinnum n (RngRing m a) = RngRing (toInteger n * m) (sinnum n a)
  
  instance (Abelian r, Group r) => LeftModule Integer (RngRing r) where
    n .* RngRing m a = RngRing (toInteger n * m) (times n a)
  
  instance (Abelian r, Group r) => RightModule Integer (RngRing r) where
    RngRing m a *. n = RngRing (toInteger n * m) (times n a)
  
  instance (Abelian r, Group r) => Group (RngRing r) where
    RngRing n a - RngRing m b = RngRing (n - m) (a - b)
    negate (RngRing n a) = RngRing (negate n) (negate a)
    subtract (RngRing n a) (RngRing m b) = RngRing (subtract n m) (subtract a b)
    times n (RngRing m a) = RngRing (toInteger n * m) (times n a)
  
  instance Rng r => Multiplicative (RngRing r) where
    RngRing n a * RngRing m b = RngRing (n*m) (times n b + times m a + a * b)
  
  instance (Commutative r, Rng r) => Commutative (RngRing r)
  
  instance Rng s => LeftModule (RngRing s) (RngRing s) where
    (.*) = (*) 
  
  instance Rng s => RightModule (RngRing s) (RngRing s) where
    (*.) = (*) 
  
  instance Rng r => Unital (RngRing r) where
    one = RngRing 1 zero
  
  instance (Rng r, Division r) => Division (RngRing r) where
    RngRing n a / RngRing m b = RngRing 0 $ (times n one + a) / (times m one + b)
  
  instance Rng r => Semiring (RngRing r) 
  
  instance Rng r => Rig (RngRing r)
  
  instance Rng r => Ring (RngRing r)
  
  -- | The rng homomorphism from r to RngRing r
  rngRingHom :: r -> RngRing r
  rngRingHom = RngRing 0
  
  -- | given a rng homomorphism from a rng r into a ring s, liftRngHom yields a ring homomorphism from the ring `r^` into `s`.
  liftRngHom :: Ring s => (r -> s) -> RngRing r -> s
  liftRngHom g (RngRing n a) = times n one + g a
  