Fixup c1035d51e to behave more like in GHC 7.6
authorHerbert Valerio Riedel <hvr@gnu.org>
Tue, 24 Jun 2014 20:58:41 +0000 (22:58 +0200)
committerHerbert Valerio Riedel <hvr@gnu.org>
Tue, 24 Jun 2014 21:30:12 +0000 (23:30 +0200)
The fix in c1035d51e (addressing #9231) was done under the assumption
that `Data.Fixed` is used only with power-of-10 `resolution`. This
follow-up fixup changes the behavior to be more consistent with the
previous behavior in GHC 7.6

For instance, for the following `B7` resolution

   > data B7
   > instance HasResolution B7 where resolution _ = 128

After this patch, the following behavior is now observable:

   > 1.070 :: Fixed B7
   1.062
   > 1.062 :: Fixed B7
   1.054

   > read "1.070" :: Fixed B7
   1.062
   > read "1.062" :: Fixed B7
   1.054

This doesn't provide the desirable "read . show == id" property
yet (which didn't hold in GHC 7.6 either), but at least `fromRational`
and `read` are consistent.

Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org>
libraries/base/Data/Fixed.hs

index b3af208..cadbb61 100644 (file)
@@ -159,9 +159,12 @@ instance (HasResolution a) => Read (Fixed a) where
 convertFixed :: forall a . HasResolution a => Lexeme -> ReadPrec (Fixed a)
 convertFixed (Number n)
  | Just (i, f) <- numberToFixed e n =
 convertFixed :: forall a . HasResolution a => Lexeme -> ReadPrec (Fixed a)
 convertFixed (Number n)
  | Just (i, f) <- numberToFixed e n =
-    return (fromInteger i + (fromInteger f / fromInteger r))
-    where r = resolution (undefined :: Fixed a) -- = 10^e
-          e = round (logBase 10 (fromInteger r) :: Double)
+    return (fromInteger i + (fromInteger f / (10 ^ e)))
+    where r = resolution (undefined :: Fixed a)
+          -- round 'e' up to help make the 'read . show == id' property
+          -- possible also for cases where 'resolution' is not a
+          -- power-of-10, such as e.g. when 'resolution = 128'
+          e = ceiling (logBase 10 (fromInteger r) :: Double)
 convertFixed _ = pfail
 
 data E0 = E0
 convertFixed _ = pfail
 
 data E0 = E0