{-- a proposal for a new structure of the number classes of Haskell-98
-}


module Numbers where

import Prelude hiding ((++), Num (..), Integral (..), Fractional (..), 
                    abs, signum, gcd, lcm)

{- af april06 
        minimal changes to actual prelude!
        no contexts, even when math demands unit
        -}
class Zeros z where
    zero :: z
    --
class Ones o where
    one :: o

class  Monoid s where           -- math definition requires emtpy as a unit
    infixr 5  ++
    (++) :: s -> s -> s                         

class  CommGroup a where        -- math definition requires zero as a unit
    infixl 6  +, -
    (+) :: a -> a -> a
    negate  :: a -> a     
    --
    (-) :: a -> a -> a
    a - b = a + (negate b)
    subtract :: a -> a -> a
    subtract =  flip (-)

class (Zeros a, Ord a, CommGroup a) => OrdGroup a where
                -- context required to allow definitions
    abs::  a -> a
    abs a = if a > zero then a else negate a
    difference :: a -> a -> a
    difference a b = abs (a - b)
                       
-----------------------------------------------------------ring---------------
class  CommRing a where         -- math. definition would require CommGroup
    infixl 7  * 
    (*) :: a -> a -> a
    sqr :: a -> a
    sqr a = a * a

     
class (OrdGroup a, CommRing a) => EuclideanRing a where
                    -- context is required for gcd and lcm
    divMod, quotRem :: a -> a -> (a,a)
    --
    quot, rem, div, mod :: a -> a -> a
    gcd, lcm :: a -> a -> a 
    even, odd :: IntegralDomain a => a -> Bool
    ---
    gcd x y = if x == zero &&  y == zero
                        then error "Prelude.gcd: gcd 0 0 is undefined"
              else gcd' (abs x) (abs y)
                         where  gcd' x y = if y == zero then x
                                            else gcd' y (x `rem` y)
    lcm x y = if x == zero then zero else
                if y == zero then zero 
                   else abs ((x `quot` (gcd x y)) * y)
    
    rem a b = f     where (i,f) = quotRem a b
    quot a b = i    where (i,f) = quotRem a b
    div a b = i     where (i,f) = divMod a b
    mod a b = f     where (i,f) = divMod a b
    
    even a = a `rem` (inc one) == zero
    
 

--------------------------------------------------------------------------
class (Zeros a, Ones a,  Ord a, CommGroup a) => IntegralDomain a where 
    inc, dec :: a -> a
    inc a = one + a
    dec a = a - one
    signum ::  a -> a      -- result is   (-1, 0, 1)
    signum a = if a > zero then one else
                if a == zero then zero else
                        (negate one)
                        
                        
class (CommRing a)  => Field a where
    infixl 7  /
          
    recip :: a -> a         -- reciprocal

    (/) :: a -> a -> a
    a / b = a * (recip b)
    
--------------------------------------------------------------------------
{-
class (Field a) => Floating a where
    pi :: a
    exp, log, sqrt :: a -> a
    (**), logBase :: a -> a -> a
    sin, cos, tan :: a -> a
    asin, acos, atan :: a -> a
    sinh, cosh, tanh :: a -> a
    asinh, acosh, atanh :: a -> a
-}



                       