Personal tools

Generic number type

From HaskellWiki

Revision as of 16:11, 20 June 2007 by Byorgey (Talk | contribs)

Jump to: navigation, search


1 Problem


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

Answer: In principle you can define a type like

data GenericNumber =
    Integer Integer
  | Rational Rational
  | Double Double
and define appropriate instances for
class et. al.


That is, when using
s you will encounter exactly the problems


type would also negate the type safety that strongly typed numbers provide, putting the burden back on the programmer to make sure they are using numbers in a type-safe way. This can lead to subtle and hard-to-find bugs, for example, if some code ends up comparing two floating-point values for equality (usually a bad idea) without the programmer realizing it.

2 Solutions


2.1 average


average xs = sum xs / fromIntegral (length xs)

and you may prefer

average :: [GenericNumber] -> GenericNumber
average xs = sum xs / genericNumberLength xs
with an appropriate implementation of
. However, there is already
and you can write
average xs = sum xs / genericLength xs

2.2 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
are interpreted as rationals itself. The second example fails, because
always returns an
number type, where
is not an instance. You should use
instead. This constructs a fraction out of two integers:
1 % 3 :: Rational
1 % floor pi :: Rational

2.3 isSquare

It may seem irksome that
is required in the function
With a
type, one could instead write
isSquare :: GenericNumber -> Bool
isSquare n = (floor . sqrt $ n) ^ 2 == n
but there is a subtle problem here: if the input happens to be represented internally by a non-integral type, this function will probably not work properly. This could be fixed by wrapping all occurrences of
by calls to
, but that's no easier (and less type-safe) than just including the call to
in the first place. The point is that by using
here, all opportunities for the type checker to warn you of problems is lost; now you, the programmer, must ensure that the underlying numeric types are always used correctly, which is made even harder by the fact that you can't inspect them.

3 See also