```{-# LANGUAGE RebindableSyntax #-}

import qualified Number.ResidueClass as Res

import qualified Algebra.PrincipalIdealDomain as PID
import qualified Algebra.IntegralDomain as Integral
import qualified Algebra.Ring           as Ring

import NumericPrelude.Base
import NumericPrelude.Numeric

import qualified Prelude        as P
import qualified NumericPrelude.Numeric as NP

{- |
like that from the Monad Transformer Library.
-}
newtype T a b = Cons {toFunc :: a -> b}

concrete :: a -> T a b -> b
concrete m (Cons r) = r m

fromRepresentative :: (Integral.C a) => a -> T a a
fromRepresentative = Cons . mod

getZero :: (Additive.C a) => T a a
getZero = Cons \$ const Additive.zero

getOne :: (Ring.C a) => T a a
getOne  = Cons \$ const NP.one

fromInteger :: (Integral.C a) => Integer -> T a a
fromInteger = fromRepresentative . NP.fromInteger

(Cons x) >>= y  =  Cons (\r -> toFunc (y (x r)) r)
return = Cons . const

getAdd :: Integral.C a => T a (a -> a -> a)

getSub :: Integral.C a => T a (a -> a -> a)
getSub = Cons Res.sub

getNeg :: Integral.C a => T a (a -> a)
getNeg = Cons Res.neg

getAdditiveVars :: Integral.C a => T a (a, a -> a -> a, a -> a -> a, a -> a)

getMul :: Integral.C a => T a (a -> a -> a)
getMul = Cons Res.mul

getRingVars :: Integral.C a => T a (a, a -> a -> a)
getRingVars = liftM2 (,) getOne getMul

getDivide :: PID.C a => T a (a -> a -> a)
getDivide = Cons Res.divide

getRecip :: PID.C a => T a (a -> a)
getRecip = Cons Res.recip

getFieldVars :: PID.C a => T a (a -> a -> a, a -> a)
getFieldVars = liftM2 (,) getDivide getRecip

monadExample :: PID.C a => T a [a]
(one',(*~)) <- getRingVars
((/~),recip') <- getFieldVars
let three = one'+one'+one'  -- is easier if only NP.fromInteger is visible
let seven = three+three+one'
return [zero'*~three, one'/~three, recip' three,
three *~ seven, one' +~ three +~ seven,
zero' -~ three, negate' three +~ seven]

runExample :: [Integer]
runExample =
let three = one+one+one
eleven = three+three+three + one+one