# Generic number type

### From HaskellWiki

(Difference between revisions)

(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

## 1 Problem

Question:

Can I have a generic numeric data type in Haskell which coversInteger

Rational

Double

Answer: In principle you can define a type like

data GenericNumber = Integer Integer | Rational Rational | Double Double

Num

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 usingGenericNumber<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

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

Data.List.genericLength

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

### 1.1 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 literals1

3

floor

Integral

Rational

%

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

## 2 See also

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