
I am not sure if this has been brought up for haskell-prime or not, but a while ago someone noticed that 'realToFrac' as specified in the report can't propagate NaN or infinity values properly since it goes through a Rational intermediate stage. this has the odd effect in ghc of making such conversions only work when optimization is used so the RULES turning Float<->Double conversion into their C counterparts fire. The proposed solution was to add NaN, +Infinity, and -Infinity to rational with the representations 0 :% 0, 1 :% 0, and -1 :% 0 respectively. Seems straightforward, (and generally useful) but we should make sure not to forget it for haskell-prime. John -- John Meacham - ⑆repetae.net⑆john⑈

John Meacham wrote:
The proposed solution was to add NaN, +Infinity, and -Infinity to rational with the representations 0 :% 0, 1 :% 0, and -1 :% 0 respectively. Seems straightforward, (and generally useful) but we should make sure not to forget it for haskell-prime.
I'm not necessarily against this, but it does fundamentally change the semantics of Ratio. Has all the behaviour been worked out for this? -- Ashley Yakeley

On Mon, Feb 27, 2006 at 05:50:38PM -0800, Ashley Yakeley wrote:
The proposed solution was to add NaN, +Infinity, and -Infinity to rational with the representations 0 :% 0, 1 :% 0, and -1 :% 0 respectively. Seems straightforward, (and generally useful) but we should make sure not to forget it for haskell-prime.
I'm not necessarily against this, but it does fundamentally change the semantics of Ratio. Has all the behaviour been worked out for this?
Well, another solution would be to define some other mechanism for converting between floating type numbers. but I would find extra expresiveness of adding NaN,etc.. to Ratio quite useful, as propagating infinities seems like a much more user friendly behavior than bottoming out. It is a fairly large change, but since all currently correct haskell programs don't create rationals with zero denominators, none of their behavior will change. I hesitate to bring it up because I fear that if we look at haskells floating point support too much we might realize just how bad it is and how tricky these things are to get right and grow despondent :) John -- John Meacham - ⑆repetae.net⑆john⑈

On 27/02/06, John Meacham
I am not sure if this has been brought up for haskell-prime or not, but a while ago someone noticed that 'realToFrac' as specified in the report can't propagate NaN or infinity values properly since it goes through a Rational intermediate stage. this has the odd effect in ghc of making such conversions only work when optimization is used so the RULES turning Float<->Double conversion into their C counterparts fire.
The proposed solution was to add NaN, +Infinity, and -Infinity to rational with the representations 0 :% 0, 1 :% 0, and -1 :% 0 respectively. Seems straightforward, (and generally useful) but we should make sure not to forget it for haskell-prime.
John
I'm almost scared to ask: does this mean we need negative zero as well? This change means that Rational is no longer a field. It makes me feel uneasy at least. Should we really expect realToFrac to propagate those values? Look at its type: realToFrac :: (Real a, Fractional b) => a -> b Nothing about the Fractional class would seem to indicate that NaN and +-Infinity should be representable. In fact, it just looks like the basic field operations, and fields don't tend to have such elements (not that we require the field axioms to hold for every instance). I personally don't see any reason that realToFrac should propagate the special error condition values of IEEE floating point types. Given its type, I'd expect it to throw an exception. - Cale

On Tue, Feb 28, 2006 at 12:44:04AM -0500, Cale Gibbard wrote:
I'm almost scared to ask: does this mean we need negative zero as well?
good point. probably.
This change means that Rational is no longer a field. It makes me feel uneasy at least. Should we really expect realToFrac to propagate those values? Look at its type: realToFrac :: (Real a, Fractional b) => a -> b Nothing about the Fractional class would seem to indicate that NaN and +-Infinity should be representable. In fact, it just looks like the basic field operations, and fields don't tend to have such elements (not that we require the field axioms to hold for every instance).
It makes me uneasy too. Perhaps we can come up with something better.
I personally don't see any reason that realToFrac should propagate the special error condition values of IEEE floating point types. Given its type, I'd expect it to throw an exception.
well, the main reason is that it is the only way we have to convert between various floating point types. If we can come up with another mechanism then perhaps that is a better solution, but it is not at all obvious to me what that other mechanism would be. John -- John Meacham - ⑆repetae.net⑆john⑈

On 28/02/06, John Meacham
On Tue, Feb 28, 2006 at 12:44:04AM -0500, Cale Gibbard wrote:
I'm almost scared to ask: does this mean we need negative zero as well?
good point. probably.
This change means that Rational is no longer a field. It makes me feel uneasy at least. Should we really expect realToFrac to propagate those values? Look at its type: realToFrac :: (Real a, Fractional b) => a -> b Nothing about the Fractional class would seem to indicate that NaN and +-Infinity should be representable. In fact, it just looks like the basic field operations, and fields don't tend to have such elements (not that we require the field axioms to hold for every instance).
It makes me uneasy too. Perhaps we can come up with something better.
I personally don't see any reason that realToFrac should propagate the special error condition values of IEEE floating point types. Given its type, I'd expect it to throw an exception.
well, the main reason is that it is the only way we have to convert between various floating point types. If we can come up with another mechanism then perhaps that is a better solution, but it is not at all obvious to me what that other mechanism would be.
How about, toRealFloat :: (RealFloat a, RealFloat b) => a -> b toRealFloat = uncurry encodeFloat . decodeFloat Presently, this doesn't quite work, but that's due to the inability of encodeFloat to produce pairs which mean NaN and -0. If we extend its codomain a bit to include those, that would seem fine. It would seem to me that if we want a conversion between IEEE floating point types, then it should be somewhere around here in the hierarchy anyway. - Cale

John Meacham wrote:
On Tue, Feb 28, 2006 at 12:44:04AM -0500, Cale Gibbard wrote:
I'm almost scared to ask: does this mean we need negative zero as well?
good point. probably.
If the point is to allow floating-point conversion to go through Ratio correctly, you might have to do that. However, I would think long and hard before actually doing this. We tried exactly this in Maple (introduce -0 in the rationals, after having implemented fully IEEE-754 floats/doubles/etc), and that broke the system in a huge number of weird ways that we could not hope to 'fix' in a sensible manner. So we backed that one change out (ie this was implemented internally, and the resulting system was completely broken for about a month as we tried to make sense of the resulting mess, then backed it out). My current belief is that floats are such a "non algebraic" (from a mathematical point of view) type that it is hopeless to try to get it to inter-operate with algebraic types (ie Fractional/Ratio). So realToFrac will necessarily lose information. Now, given realToFrac, the sign of a real number, isNaN, and isInfinity, one *can* construct an algebraic representation which will be complete, but it will have to contain more information than can be coded in a Fractional object. What *problem* are you actually trying to solve here? If it is "conversion between floating point types", then there are other solutions that do not need to ``pollute'' exact arithmetic. I did not see any tickets on this -- did I miss it/them? This is one issue where I should go and contribute, as I've been part of a team that has done just this to a programming language before, so at least I can claim to know the pitfalls to avoid! Jacques

Cale Gibbard wrote:
This change means that Rational is no longer a field. It makes me feel uneasy at least. Should we really expect realToFrac to propagate those values? Look at its type: realToFrac :: (Real a, Fractional b) => a -> b Nothing about the Fractional class would seem to indicate that NaN and +-Infinity should be representable. In fact, it just looks like the basic field operations, and fields don't tend to have such elements (not that we require the field axioms to hold for every instance).
I know for a fact that the Ratio type excludes 1%0 and 0%0 from the allowed values by design rather than by mistake. I discussed it with Joe Fasel many years ago, and he convinced me it was a bad idea. But I admit that the realToFrac argument carries some weight, even if I had never even thought about the problem before. -- Lennart
participants (5)
-
Ashley Yakeley
-
Cale Gibbard
-
Jacques Carette
-
John Meacham
-
Lennart Augustsson