
Am Donnerstag 04 März 2010 16:45:03 schrieb Nick Bowler:
On 16:20 Thu 04 Mar , Daniel Fischer wrote:
Yes, without rules, realToFrac = fromRational . toRational.
<snip>
I think one would have to add {-# RULES #-} pragmas to Graphics.Rendering.OpenGL.Raw.Core31.TypesInternal, along the lines of
{-# RULES "realToFrac/CDouble->GLdouble" realToFrac x = GLdouble x "realToFrac/GLdouble -> CDouble" realToFrac (GLdouble x) = x #-}
These rules are, alas, *not* equivalent to fromRational . toRational.
But these rules are probably what one really wants for a [C]Double <-> GLdouble conversion.
Unfortunately, realToFrac is quite broken with respect to floating point conversions, because fromRational . toRational is entirely the wrong thing to do.
"entirely"? For realToFrac :: (Real a, Fractional b) => a -> b I think you can't do much else that gives something more or less reasonable. For (almost?) any concrete conversion, you can do something much better (regarding performance and often values), but I don't think there's a generic solution.
I've tried to start some discussion on the haskell-prime mailing list about fixing this wart. In the interim, the OpenGL package could probably provide its own CDouble<=>GLDouble conversions, but sadly
s/could/should/, IMO.
the only way to "correctly" perform Double<=>CDouble is unsafeCoerce.
Are you sure? In Foreign.C.Types, I find {-# RULES "realToFrac/a->CFloat" realToFrac = \x -> CFloat (realToFrac x) "realToFrac/a->CDouble" realToFrac = \x -> CDouble (realToFrac x) "realToFrac/CFloat->a" realToFrac = \(CFloat x) -> realToFrac x "realToFrac/CDouble->a" realToFrac = \(CDouble x) -> realToFrac x #-} , so if you have a {-# RULES "realToFrac/Double->Double" realToFrac = id :: Double -> Double #-} (why isn't that in GHC.Real, anyway?), it should do the correct thing - not that it's prettier than unsafeCoerce.