Commit 7c38e985 authored by puffnfresh's avatar puffnfresh Committed by Herbert Valerio Riedel

Make `read . show = id` for Data.Fixed (fix #9240)

The QuickCheck property now succeeds:

    prop :: Fixed B7 -> Bool
    prop a = read (show a) == a

This changes the Show instance for Fixed to round up, rather than down
when calculating a digit. This needs to happen because Read also
rounds down:

    data B7

    instance HasResolution B7 where
      resolution _ = 128

    1 / 128 = 0.0078125

    read "0.007" = (0.000 :: Fixed B7)

Here is an example of the change to Show:

    showFixed False (0.009 :: Fixed B7)

    -- Broken: "0.007"
    -- Fixed:  "0.008"

And now Read can continue to round down:

    read "0.008" = (0.0078125 :: Fixed B7)

Reviewed By: hvr, ekmett

Differential Revision: https://phabricator.haskell.org/D547
parent 6b063ef2
......@@ -143,7 +143,9 @@ showFixed chopTrailingZeros fa@(MkFixed a) = (show i) ++ (withDot (showIntegerZe
-- enough digits to be unambiguous
digits = ceiling (logBase 10 (fromInteger res) :: Double)
maxnum = 10 ^ digits
fracNum = div (d * maxnum) res
-- read floors, so show must ceil for `read . show = id` to hold. See #9240
fracNum = divCeil (d * maxnum) res
divCeil x y = (x + y - 1) `div` y
instance (HasResolution a) => Show (Fixed a) where
show = showFixed False
......
......@@ -128,6 +128,8 @@
together with a new exception `AllocationLimitExceeded`.
* Make `read . show = id` for `Data.Fixed` (#9240)
## 4.7.0.2 *Dec 2014*
* Bundled with GHC 7.8.4
......
......@@ -3,6 +3,11 @@ module Main (main) where
import Data.Fixed
data B7
instance HasResolution B7 where
resolution _ = 128
main :: IO ()
main = do doit 38.001
doit 38.009
......@@ -14,6 +19,8 @@ main = do doit 38.001
doit (-38.01)
doit (-38.09)
print (read "-38" :: Centi)
print (read "0.008" :: Fixed B7)
print (read "-0.008" :: Fixed B7)
doit :: Centi -> IO ()
doit c = do let s = show c
......
......@@ -16,3 +16,5 @@
-38.09
-38.09
-38.00
0.008
-0.008
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment