[Haskell-cafe] ANN: convertible (first release)

wren ng thornton wren at freegeek.org
Wed Jan 28 17:28:41 EST 2009


John Goerzen wrote:
> wren ng thornton wrote:
> > I once again point out that realToFrac is *wrong* for converting from  
> > Float or Double.
> >
> >     > realToFrac (1/0::Float) ::Double
> >     3.402823669209385e38
> 
> Yes, I understand what you are saying and agree with you.  But there
> is nothing better in the standard library, and I did not feel it was
> worth adding another dependency to the package simply for the sake of
> this sort of thing.  People that need it can get it for themselves and
> write their own instance of Convertible if they wish.

Then add a wrapper that calls Prelude.isNaN and Prelude.isInfinite in 
order to guard against these values just like you do for conversion from 
unbounded types to bounded types.

Avoiding a trivial dependency is no excuse for avoiding correctness.


> > These exceptional values are not uncommon and should be dealt with  
> > correctly. The code to do this is already written in  
> > logfloat:Data.Number.Transfinite[1], simply use the realToFrac method of  
> > the RealToFrac class instead of the Prelude's version which is broken.
> 
> I wonder if you would consider submitting a patch to base?  It seems
> that this is a sore problem there, and ideally should be dealt with
> properly in base.

As Bertram Felgenhauer says, it's not as easy as fixing base; the 
problem is an error in the Haskell98 specification. The Float and Double 
types contain exceptional values which cannot be represented in Rational 
(by definition). The only Haskell98 solution is to raise an error when 
attempting to convert those values into Rational, which isn't much of an 
improvement.

At some point I may propose the logfloat solution for Haskell Prime. 
MPTCs have already been accepted, but the logfloat solution does 
necessitate additional non-insignificant changes. For example there 
should be a class for partially ordered types[1][2]. To reduce code 
bloat a PartialOrd instance should be available whenever an Ord instance 
is; which means opening the whole can of worms about changing the 
numeric class hierarchy and changes to the type-class mechanism in order 
to simplify defining all those different instances. So far I've held off 
on proposing the solution because I haven't worked out the best way to 
resolve these issues with minimal changes.


[1] The Ord instance for Float and Double is also wrong, since NaN means 
there's no total ordering (and the existence of NaN is necessitated by 
the existence of Infinity). In addition to the fact that partial 
orderings are more common than total orderings, this means we should 
have a partial ordering class anyways.

[2] There's also the issue of what type the partial and total comparison 
functions should return. Logfloat uses Maybe Ordering to make use of the 
various helper functions and type classes defined on those types, but 
for performance reasons we would much rather prefer a flat type. It's 
inelegant to have both Ordering and PartialOrdering types; and it's 
hackish to just have PartialOrdering and have Ord ensure that the 
NotComparable value is never generated.

-- 
Live well,
~wren


More information about the Haskell-Cafe mailing list