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

bretm bret_x at hotmail.com
Sun Jun 3 22:59:08 EDT 2007

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.

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).

I'd also like to implement approxRational since this can be done in a
straightforward manner with my data type, but this appears to be just a
library function in the Ratio library and not a function defined in a class,
and is dependent on the toRational function which doesn't make sense for a
data type that can represent irrational values exactly.

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.)  3) If I'm right about toRational
requiring "full precision", why was implementing this made a requirement for
implementing properFraction? 4) Why on earth is there a class called "Real"
that requires the ability to convert to Rational with full precision, which
can't be done with all real numbers?

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 this data type it's
straightforward to implement the Num and Fractional classes and get full
arithmetic operations +, -, *, /, etc. The properFraction function also
makes sense: there's an integer portion equal to 1 in this case, and a
fractional portion equal to (-1, 5, 2), exactly. So truncate, round,
ceiling, and floor make sense (in RealFrac). But toRational can't be
implemented with "full precision". 

With this example you can also see how approxRational is a perfectly good
idea, and would be something likely to be needed, but this function isn't a
class function designed to be implemented by custom data types.

It seems to me (with my meager few days of Haskell experience) that
approxRational should have been part of the Real class, and that toRational
should be relegated the Ratio library instead. Or else, that the functions
that are in RealFrac should be in the Fractional class instead. So I'm
guessing there are some good reasons for having RealFrac in addition to
Fractional that I'm not yet aware of.

View this message in context: http://www.nabble.com/Why-does-the-class-called-%22Real%22-support-only-rationals%2C-and-not-all-reals--tf3862820.html#a10943139
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

More information about the Haskell-Cafe mailing list