on master help sign in
Use Scientific.fromRealFloat and Scientific.toRealFloat
commitcd9dd568fc53b17f119ead572dd8b1b935081cef authorBas van Dijk <v.dijk.bas@gmail.com> dateTue 13 May 2014, 02:44 (12 years ago) parent6f6e1a3
1 file changed+9−21
Data/Aeson/Types/Instances.hs+9−21
Data/Aeson/Types/Instances.hs+9−21
@@ -56,7 +56,7 @@ import Data.Aeson.Functions
5656import Data.Aeson.Types.Class
5757import Data.Aeson.Types.Internal
5858import Data.Scientific (Scientific)
59−import qualified Data.Scientific as Scientific (coefficient, base10Exponent, fromFloatDigits)
59+import qualified Data.Scientific as Scientific (coefficient, base10Exponent, fromRealFloat, toRealFloat)
6060import Data.Attoparsec.Number (Number(..))
6161import Data.Fixed
6262import Data.Hashable (Hashable(..))
@@ -168,7 +168,7 @@ instance ToJSON Double where
168168 {-# INLINE toJSON #-}
169169
170170instance FromJSON Double where
171− parseJSON = parseFractional "Double"
171+ parseJSON = parseRealFloat "Double"
172172 {-# INLINE parseJSON #-}
173173
174174instance ToJSON Number where
@@ -187,7 +187,7 @@ instance ToJSON Float where
187187 {-# INLINE toJSON #-}
188188
189189instance FromJSON Float where
190− parseJSON = parseFractional "Float"
190+ parseJSON = parseRealFloat "Float"
191191 {-# INLINE parseJSON #-}
192192
193193instance ToJSON (Ratio Integer) where
@@ -781,7 +781,7 @@ typeMismatch expected actual =
781781realFloatToJSON :: RealFloat a => a -> Value
782782realFloatToJSON d
783783 | isNaN d || isInfinite d = Null
784− | otherwise = Number $ Scientific.fromFloatDigits d
784+ | otherwise = Number $ Scientific.fromRealFloat d
785785{-# INLINE realFloatToJSON #-}
786786
787787scientificToNumber :: Scientific -> Number
@@ -793,23 +793,11 @@ scientificToNumber s
793793 c = Scientific.coefficient s
794794{-# INLINE scientificToNumber #-}
795795
796−parseFractional :: Fractional a => String -> Value -> Parser a
797−parseFractional _ (Number s) = pure $ scientificToFractional s
798−parseFractional _ Null = pure (0/0)
799−parseFractional expected v = typeMismatch expected v
800−{-# INLINE parseFractional #-}
801−
802−-- | Convert an /untrusted/ scientific value to a fractional.
803−scientificToFractional :: Fractional a => Scientific -> a
804−scientificToFractional s = realToFrac s
805− -- TODO: Using realToFrac is unsafe here. Do something similar as
806− -- scientificToIntegral. The following might work but I'm not sure
807− -- this doesn't introduce rounding errors:
808− --
809− -- fromInteger c * 10 ^ e
810− -- where
811− -- e = Scientific.base10Exponent s
812− -- c = Scientific.coefficient s
796+parseRealFloat :: RealFloat a => String -> Value -> Parser a
797+parseRealFloat _ (Number s) = pure $ Scientific.toRealFloat s
798+parseRealFloat _ Null = pure (0/0)
799+parseRealFloat expected v = typeMismatch expected v
800+{-# INLINE parseRealFloat #-}
813801
814802parseIntegral :: Integral a => String -> Value -> Parser a
815803parseIntegral expected = withScientific expected $ pure . floor