Concerning Haskell 1.3 + n
--------------------------
Am I alone in finding the standard prelude for Haskell unsatisfactory
when it comes to dealing with different sorts of numbers and how they
are related? 
I use Gofer 2.28 and a home-brewed prelude. Multi-parameter classes
let me do things that I do not think can be done in Haskell, but which
definitely make life simpler.

In my prelude I have 3 built-in types of number: 

     Int >--> Rational >--> Float

and a type constructor of kind *->* called Gauss, with a type synonym

type Complex = Gauss Float

giving me a hierarchy

          Int >---------> Rational >---------> Float
           V                 V                  V
           |                 |                  |
           V                 V                  V
        Gauss Int >-->  Gauss Rational >-->   Complex

I have no class Num. Instead I have

class Add a where
     (+),(-) :: BinOp a
     negate  :: a -> a
     zero    :: a
     negate x = zero - x

because there are lots of things you want to use additive notation with
(vectors, functions taking values in additive types, etc) besides
numbers. Then I have

class LeftMul a b where
    (*) :: a -> b -> b

with instance declarations defining left scalar multiplication on
vectors, etc, and permitting left multiplication of numbers in the
hierarchy shown above by numbers lower down the hierarchy. So for
example

          (2:/3)*(1.0 :+! pi)

is accepted, as a complex number left multiplied by a rational.
Similarly I have

class Div a b where
     (/) :: a -> b -> a

and instance declarations so that I can divide a number by anything
lower in the hierarchy. It is a great relief to be able to use pi/2
rather than pi/2.0 every time.

For raising things to integer powers I use

class LeftMul a a => Mult a where
     unit     :: a
     (^)      :: a -> Int -> a
     x ^ 0     = unit
     x ^ 1     = x
     x ^ (2*n) = (x*x)^n
     x ^ (2*n+1) = x*(x*x)^n

and for implementing the standard overloading of trigonometric functions
I also use

class (Div a a, Add a, Mult a, Div a Int, LeftMul Int a) => Exp a where
     exp, log, cosh, sinh, tanh :: a -> a
     cosh x = (exp(x) + exp(-x))/2
     sinh x = (exp(x) - exp(-x))/2
     tanh x = (a-unit)/(a+unit) where a = exp(2*x)

I am not suggesting that everybody would want to do this, but the
present use of Num is far too monolithic and inflexible for sensible
exploitation of Haskell for mathematical purposes. I would be interested
to hear what others feel about this.

-- Gavin Wraith


Reply via email to