# Difference between revisions of "Generic number type"

(extracted from the Haskell-Cafe discussion) |
m |
||

Line 17: | Line 17: | ||

Floating point numbers are imprecise - a/b*b=a does not hold in general. |
Floating point numbers are imprecise - a/b*b=a does not hold in general. |
||

Rationals are precise but pi and sqrt 2 are not rational. |
Rationals are precise but pi and sqrt 2 are not rational. |
||

− | That is, when using |
+ | That is, when using <hask>GenericNumber<hask>s you will encounter exactly the problems |

that all scripting language users have encountered so far (or ignored :-). |
that all scripting language users have encountered so far (or ignored :-). |
||

## Revision as of 12:16, 20 June 2007

## Problem

Question:
Can I have a generic numeric data type in Haskell which covers `Integer`

, `Rational`

, `Double`

and so on, like it is done in scripting languages like Perl and MatLab?

Answer: In principle you can define a type like

```
data GenericNumber =
Integer Integer
| Rational Rational
| Double Double
```

and define appropriate instances for `Num`

class et. al.
However you will find that it is difficult to implement these methods in a way that is appropriate for each use case.
There is simply no type that can emulate the others.
Floating point numbers are imprecise - a/b*b=a does not hold in general.
Rationals are precise but pi and sqrt 2 are not rational.
That is, when using `GenericNumber<hask>s you will encounter exactly the problems that all scripting language users have encountered so far (or ignored :-). == Solutions == It is strongly advised to carefully check whether a GenericNumber is indeed useful for your application. So let's revisit some examples and their idiomatic solutions in plain Haskell 98. === average === You may find it cumbersome to write <haskell> average :: Fractional a => [a] -> a average xs = sum xs / fromIntegral (length xs) </haskell> and you may prefer <haskell> average :: [GenericNumber] -> GenericNumber average xs = sum xs / genericNumberLength xs </haskell> with an appropriate implementation of <hask>genericNumberLength`

.
However, there is already `Data.List.genericLength`

and you can write

```
average :: Fractional a => [a] -> a
average xs = sum xs / genericlength xs
```

### ratios

You find it easy to write

```
1 / 3 :: Rational
```

but uncomfortable that

```
1 / floor pi :: Rational
```

does not work.
The first example works, because the numeric literals `1`

and `3`

are interpreted as rationals itself.
The second example fails, because `floor`

always returns an `Integral`

number type, where `Rational`

is not an instance.
You should use `%`

instead. This constructs a fraction out of two integers:

```
1 % 3 :: Rational
1 % floor pi :: Rational
```

## See also

- Suggestions for implementing a generic number type: http://www.haskell.org/pipermail/haskell-cafe/2007-June/027092.html