Generic number type
From HaskellWiki
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
Categories: FAQ | Mathematics | Idioms
