on master help sign in
Use Scientific.fromRealFloat and Scientific.toRealFloat
cd9dd56Bas van Dijk
Data/Aeson/Types/Instances.hs+9−21
@@ -56,7 +56,7 @@ import Data.Aeson.Functions
56import Data.Aeson.Types.Class
56import Data.Aeson.Types.Class
57import Data.Aeson.Types.Internal
57import Data.Aeson.Types.Internal
58import Data.Scientific (Scientific)
58import Data.Scientific (Scientific)
59−import qualified Data.Scientific as Scientific (coefficient, base10Exponent, fromFloatDigits)
59+import qualified Data.Scientific as Scientific (coefficient, base10Exponent, fromRealFloat, toRealFloat)
60import Data.Attoparsec.Number (Number(..))
60import Data.Attoparsec.Number (Number(..))
61import Data.Fixed
61import Data.Fixed
62import Data.Hashable (Hashable(..))
62import Data.Hashable (Hashable(..))
@@ -168,7 +168,7 @@ instance ToJSON Double where
168 {-# INLINE toJSON #-}
168 {-# INLINE toJSON #-}
169
169
170instance FromJSON Double where
170instance FromJSON Double where
171− parseJSON = parseFractional "Double"
171+ parseJSON = parseRealFloat "Double"
172 {-# INLINE parseJSON #-}
172 {-# INLINE parseJSON #-}
173
173
174instance ToJSON Number where
174instance ToJSON Number where
@@ -187,7 +187,7 @@ instance ToJSON Float where
187 {-# INLINE toJSON #-}
187 {-# INLINE toJSON #-}
188
188
189instance FromJSON Float where
189instance FromJSON Float where
190− parseJSON = parseFractional "Float"
190+ parseJSON = parseRealFloat "Float"
191 {-# INLINE parseJSON #-}
191 {-# INLINE parseJSON #-}
192
192
193instance ToJSON (Ratio Integer) where
193instance ToJSON (Ratio Integer) where
@@ -781,7 +781,7 @@ typeMismatch expected actual =
781realFloatToJSON :: RealFloat a => a -> Value
781realFloatToJSON :: RealFloat a => a -> Value
782realFloatToJSON d
782realFloatToJSON d
783 | isNaN d || isInfinite d = Null
783 | isNaN d || isInfinite d = Null
784− | otherwise = Number $ Scientific.fromFloatDigits d
784+ | otherwise = Number $ Scientific.fromRealFloat d
785{-# INLINE realFloatToJSON #-}
785{-# INLINE realFloatToJSON #-}
786
786
787scientificToNumber :: Scientific -> Number
787scientificToNumber :: Scientific -> Number
@@ -793,23 +793,11 @@ scientificToNumber s
793 c = Scientific.coefficient s
793 c = Scientific.coefficient s
794{-# INLINE scientificToNumber #-}
794{-# INLINE scientificToNumber #-}
795
795
796−parseFractional :: Fractional a => String -> Value -> Parser a
796+parseRealFloat :: RealFloat a => String -> Value -> Parser a
797−parseFractional _ (Number s) = pure $ scientificToFractional s
797+parseRealFloat _ (Number s) = pure $ Scientific.toRealFloat s
798−parseFractional _ Null = pure (0/0)
798+parseRealFloat _ Null = pure (0/0)
799−parseFractional expected v = typeMismatch expected v
799+parseRealFloat expected v = typeMismatch expected v
800−{-# INLINE parseFractional #-}
800+{-# INLINE parseRealFloat #-}
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
813
801
814parseIntegral :: Integral a => String -> Value -> Parser a
802parseIntegral :: Integral a => String -> Value -> Parser a
815parseIntegral expected = withScientific expected $ pure . floor
803parseIntegral expected = withScientific expected $ pure . floor