-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use scientific to fix floating point rounding problems #58
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
packages: . | ||
|
||
package HsYAML | ||
flags: +exe | ||
flags: +exe | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,6 @@ | |
{-# LANGUAGE GADTs #-} | ||
{-# LANGUAGE OverloadedStrings #-} | ||
{-# LANGUAGE RecordWildCards #-} | ||
{-# LANGUAGE Safe #-} | ||
|
||
-- | | ||
-- Copyright: © Herbert Valerio Riedel 2015-2018 | ||
|
@@ -103,6 +102,7 @@ import qualified Control.Monad.Fail as Fail | |
import qualified Data.ByteString as BS | ||
import qualified Data.ByteString.Lazy as BS.L | ||
import qualified Data.Map as Map | ||
import Data.Scientific | ||
import qualified Data.Text as T | ||
|
||
import Data.YAML.Dumper | ||
|
@@ -473,11 +473,11 @@ instance FromYAML Word32 where parseYAML = parseInt "Word32" | |
instance FromYAML Word64 where parseYAML = parseInt "Word64" | ||
|
||
|
||
instance FromYAML Double where | ||
instance FromYAML Scientific where | ||
parseYAML = withFloat "!!float" pure | ||
Comment on lines
-476
to
477
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the rationale for removing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess there's an argument for going either way. My thought was that it's mainly there for the vales actually supported as scalar primitives, and since this PR changes the scalar numeric primitive from Double to Scientific, that seemed to be the obvious route to go. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, we also provide instances for types like |
||
|
||
-- | Operate on @tag:yaml.org,2002:float@ node (or fail) | ||
withFloat :: String -> (Double -> Parser a) -> Node Pos -> Parser a | ||
withFloat :: String -> (Scientific -> Parser a) -> Node Pos -> Parser a | ||
withFloat _ f (Scalar pos (SFloat b)) = fixupFailPos pos (f b) | ||
withFloat expected _ v = typeMismatch expected v | ||
|
||
|
@@ -679,7 +679,7 @@ instance Loc loc => ToYAML (Node loc) where | |
instance ToYAML Bool where | ||
toYAML = Scalar () . SBool | ||
|
||
instance ToYAML Double where | ||
instance ToYAML Scientific where | ||
toYAML = Scalar () . SFloat | ||
|
||
instance ToYAML Int where toYAML = Scalar () . SInt . toInteger | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
{-# LANGUAGE DeriveGeneric #-} | ||
{-# LANGUAGE Safe #-} | ||
|
||
-- | | ||
-- Copyright: © Herbert Valerio Riedel 2015-2018 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
{-# LANGUAGE DeriveGeneric #-} | ||
{-# LANGUAGE OverloadedStrings #-} | ||
{-# LANGUAGE RecordWildCards #-} | ||
{-# LANGUAGE Safe #-} | ||
{-# LANGUAGE ScopedTypeVariables #-} | ||
|
||
-- | | ||
|
@@ -31,6 +30,7 @@ module Data.YAML.Schema.Internal | |
import qualified Data.Char as C | ||
import qualified Data.Map as Map | ||
import qualified Data.Set as Set | ||
import Data.Scientific | ||
import qualified Data.Text as T | ||
import Numeric (readHex, readOct) | ||
import Text.Parsec as P | ||
|
@@ -42,11 +42,11 @@ import qualified Data.YAML.Event as YE | |
import Util | ||
|
||
-- | Primitive scalar types as defined in YAML 1.2 | ||
data Scalar = SNull -- ^ @tag:yaml.org,2002:null@ | ||
| SBool !Bool -- ^ @tag:yaml.org,2002:bool@ | ||
| SFloat !Double -- ^ @tag:yaml.org,2002:float@ | ||
| SInt !Integer -- ^ @tag:yaml.org,2002:int@ | ||
| SStr !Text -- ^ @tag:yaml.org,2002:str@ | ||
data Scalar = SNull -- ^ @tag:yaml.org,2002:null@ | ||
| SBool !Bool -- ^ @tag:yaml.org,2002:bool@ | ||
| SFloat !Scientific -- ^ @tag:yaml.org,2002:float@ | ||
| SInt !Integer -- ^ @tag:yaml.org,2002:int@ | ||
| SStr !Text -- ^ @tag:yaml.org,2002:str@ | ||
|
||
| SUnknown !Tag !Text -- ^ unknown/unsupported tag or untagged (thus unresolved) scalar | ||
deriving (Eq,Ord,Show,Generic) | ||
|
@@ -271,10 +271,10 @@ coreDecodeInt t | |
-- | ||
-- > -? ( 0 | [1-9] [0-9]* ) ( \. [0-9]* )? ( [eE] [-+]? [0-9]+ )? | ||
-- | ||
jsonDecodeFloat :: T.Text -> Maybe Double | ||
jsonDecodeFloat :: T.Text -> Maybe Scientific | ||
jsonDecodeFloat = either (const Nothing) Just . parse float "" | ||
where | ||
float :: Parser Double | ||
float :: Parser Scientific | ||
float = do | ||
-- -? | ||
p0 <- option "" ("-" <$ char '-') | ||
|
@@ -306,12 +306,12 @@ jsonDecodeFloat = either (const Nothing) Just . parse float "" | |
-- | ||
-- > [-+]? ( \. [0-9]+ | [0-9]+ ( \. [0-9]* )? ) ( [eE] [-+]? [0-9]+ )? | ||
-- | ||
coreDecodeFloat :: T.Text -> Maybe Double | ||
coreDecodeFloat :: T.Text -> Maybe Scientific | ||
coreDecodeFloat t | ||
| Just j <- Map.lookup t literals = Just j -- short-cut | ||
| otherwise = either (const Nothing) Just . parse float "" $ t | ||
where | ||
float :: Parser Double | ||
float :: Parser Scientific | ||
float = do | ||
-- [-+]? | ||
p0 <- option "" (("-" <$ char '-') P.<|> "" <$ char '+') | ||
|
@@ -449,15 +449,11 @@ coreSchemaEncoder = SchemaEncoder{..} | |
encodeBool :: Bool -> T.Text | ||
encodeBool b = if b then "true" else "false" | ||
|
||
-- | Encode Double | ||
-- | Encode Scientific | ||
-- | ||
-- @since 0.2.0 | ||
encodeDouble :: Double -> T.Text | ||
encodeDouble d | ||
| d /= d = ".nan" | ||
| d == (1/0) = ".inf" | ||
| d == (-1/0) = "-.inf" | ||
| otherwise = T.pack . show $ d | ||
encodeDouble :: Scientific -> T.Text | ||
encodeDouble d = T.pack . show $ d | ||
Comment on lines
+455
to
+456
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function should be named There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, is there a more efficient way to perform this encoding? |
||
|
||
-- | Encode Integer | ||
-- | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you undo this change?