[Haskell-cafe] Why does the class called "Real" support only rationals, and not all reals?

Henning Thielemann lemming at henning-thielemann.de
Mon Jun 4 09:47:14 EDT 2007

On Sun, 3 Jun 2007, bretm wrote:

> I just got started learning Haskell a few days ago. I've implemented a
> numeric data type that can represent some irrational numbers exactly, and
> I'd like to instantiate the RealFrac class so I can do truncate, round,
> etc., in the most natural way in the language.

There are several things that are inconvenient in the numeric part of
Haskell 98 Prelude. As always I suggest a look at alternative numeric
class hierarchies, like NumericPrelude:

Is your approach more like symbolic calculation or more like a
representation for computable reals?

> Implementing properFraction (which is in RealFrac) would not a problem at
> all, but implementing RealFrac requires implementing Real, which has the
> function toRational, which Haskell 98 says "returns the rational equivalent
> of its real argument with full precision" which isn't possible for this
> number type (which includes irrationals).

This obviously assumes, that all representations of reals in a computer
must be actually rationals. But in Haskell with lazy evaluation this is
not true:

> So my questions are: 1) Am I understanding the Haskell numeric classes
> correctly by thinking that to define properFraction I also have to define
> (incorrectly in this case) the toRational function?  2) Is a literal reading
> of Haskell 98 necessary for toRational or can it just be approximate? (Seems
> like not, since there's approxRational, and no other way to indicate the
> desired accuracy for toRational.)

In your case approximate would be the only possibility, I guess. Like
computations with Float and Double are approximate.

> As an example, consider a data type that can represent a quadratic surd,
> e.g. (1, 5, 2) might mean (1 + (sqrt 5)) / 2.

With NumericPrelude you can work with such numbers using polynomials
modulo the "polynomial" (x^2-5).

$ make ghci
*Main> ResidueClass.concrete (polynomial [-5,0,1::Rational]) (polyResidueClass [1,1] / 2 * polyResidueClass[1,1] / 2)
Polynomial.fromCoeffs [3 % 2,1 % 2]


(1 + sqrt 5) / 2  *  (1 + sqrt 5) / 2   =   (3 + sqrt 5) / 2

More information about the Haskell-Cafe mailing list