Hi John,

| This is a "bug" in hugs.
| 
| To illustrate the problem, the next floating point number after 
| 5.0 is 5.00000047,
| which hugs also prints as 5.0. One might argue that to display it 
| as 5.0000005 would
| be misleading, since this number is the closest representable to 
| everything from 
| 5.0000003 to 5.0000007. On the other hand, to print only the 
| "certain" digits makes
| show many-to-one, with unfortunate consequences when show and read are
| used as a portable way to store data.
| 
| In fact, hugs' behaviour isn't consistent with the Haskell 98 report.
| ...
| This behaviour is actually documented in the hugs manual, under 
| "conformance with Haskell 98". So as a documented bug, it must be
| a feature -- but perhaps one which might be removed in a future version?

It looks like this might actually be a bug in the Hugs documentation:
the comment that you refer to should perhaps be removed.  Hugs used to differ
from what the Haskell report specified, which is when that comment was
added to the Hugs manual.  But as far as I can tell, the Haskell 98 report
eliminated this discrepancy by avoiding saying anything much about how
Floats or Doubles should be displayed.  The showFloat function from the
Numeric library could be used to implement the show function, but this
isn't required.  And while the Hugs behavior doesn't suit all users
(e.g., those who are interested in every last bit), it is arguably more
appropriate for others (which is why the designers of C chose it as
their default).

The Numeric.showFloat function is there for the more expert programmers
who care about the last few bits after the floating point.  That's the
function that a Haskell programmer should use if they need this kind of
functionality.  I can imagine a complaint along the lines of: but I can't
use Numeric.showFloat because I'm really using "show" on a more complex
data structure, and it doesn't use Numeric.showFloat.  Indeed.  But that's
an argument against the use of overloading, not about how numbers are
displayed.  An overloaded operator can only have one interpretation at
any given type, and if you find yourself with two useful operations, then
you have a problem.  Whichever you choose will be wrong for somebody.
(Possible solutions to this might be found in the use of implicit parameters,
or in a beefed up showsPrec function that takes more than an integer
precedence as its argument.)

The argument that show/read can be used as a portable way to store data
doesn't work for Haskell because the report does not guarantee a portable
implementation for Float and Doubles.  String representations are for
humans; for the benefit of machines, a binary representation would be
better.  And for portability, a portable binary representation is needed.

Finally, as I've said many times, Hugs is not the right language to choose
if you are interested in doing careful floating point work.  An example
that Jerzy mentioned recently was the fact that, by default, floating point
numbers in Hugs (both Float and Double) are represented by single precision
C floats.  Last time the language lawyers looked at this, the consensus
seemed to be that this was technically legal, but obviously not ideal.
Double precision floats can be supported in Hugs, but their implementation
requires a non-portable hack, and so they are turned off by default (much
to Jerzy's frustration, I'm afraid :-().

All the best,
Mark

Reply via email to