
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