sv 1.2 → 1.3
raw patch · 7 files changed
+75/−48 lines, 7 filesdep ~basedep ~bifunctorsdep ~lensPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, bifunctors, lens, semigroupoids, sv-core
API changes (from Hackage documentation)
- Data.Sv: infixl 1 >>==
- Data.Sv: infixl 5 .:
- Data.Sv: infixr 1 ==<<
+ Data.Sv: infixl 4 >$
- Data.Sv: (==<<) :: () => a -> DecodeValidation e b -> Decode e s a -> Decode e s b
+ Data.Sv: (==<<) :: () => (a -> DecodeValidation e b) -> Decode e s a -> Decode e s b
- Data.Sv: (>>==) :: () => Decode e s a -> a -> DecodeValidation e b -> Decode e s b
+ Data.Sv: (>>==) :: () => Decode e s a -> (a -> DecodeValidation e b) -> Decode e s b
- Data.Sv: choose :: Decidable f => a -> Either b c -> f b -> f c -> f a
+ Data.Sv: choose :: Decidable f => (a -> Either b c) -> f b -> f c -> f a
- Data.Sv: chosen :: Decidable f => f b -> f c -> f Either b c
+ Data.Sv: chosen :: Decidable f => f b -> f c -> f (Either b c)
- Data.Sv: class Functor f => Alt (f :: * -> *)
+ Data.Sv: class Functor f => Alt (f :: Type -> Type)
- Data.Sv: class Contravariant (f :: * -> *)
+ Data.Sv: class Contravariant (f :: Type -> Type)
- Data.Sv: class Divisible f => Decidable (f :: * -> *)
+ Data.Sv: class Divisible f => Decidable (f :: Type -> Type)
- Data.Sv: class Contravariant f => Divisible (f :: * -> *)
+ Data.Sv: class Contravariant f => Divisible (f :: Type -> Type)
- Data.Sv: contramap :: Contravariant f => a -> b -> f b -> f a
+ Data.Sv: contramap :: Contravariant f => (a -> b) -> f b -> f a
- Data.Sv: decode :: Traversable f => Decode' ByteString a -> f Vector ByteString -> DecodeValidation ByteString f a
+ Data.Sv: decode :: Traversable f => Decode' ByteString a -> f (Vector ByteString) -> DecodeValidation ByteString (f a)
- Data.Sv: decodeEither :: () => s -> Either DecodeError e a -> Decode e s a
+ Data.Sv: decodeEither :: () => (s -> Either (DecodeError e) a) -> Decode e s a
- Data.Sv: decodeEither' :: () => e -> DecodeError e' -> s -> Either e a -> Decode e' s a
+ Data.Sv: decodeEither' :: () => (e -> DecodeError e') -> (s -> Either e a) -> Decode e' s a
- Data.Sv: decodeMay :: () => DecodeError e -> s -> Maybe a -> Decode e s a
+ Data.Sv: decodeMay :: () => DecodeError e -> (s -> Maybe a) -> Decode e s a
- Data.Sv: divide :: Divisible f => a -> (b, c) -> f b -> f c -> f a
+ Data.Sv: divide :: Divisible f => (a -> (b, c)) -> f b -> f c -> f a
- Data.Sv: lose :: Decidable f => a -> Void -> f a
+ Data.Sv: lose :: Decidable f => (a -> Void) -> f a
Files
- bench/bench.hs +3/−1
- changelog.md +4/−0
- sv.cabal +15/−15
- test/Data/Sv/CassavaTest.hs +19/−15
- test/Data/Sv/DecodeTest.hs +9/−9
- test/Data/Sv/EncodeTest.hs +3/−3
- test/Data/Sv/RoundTripsDecodeEncode.hs +22/−5
bench/bench.hs view
@@ -20,7 +20,9 @@ main = defaultMain [ bench "double" $ nf (pd D.double) doublesC- , bench "rational" $ nf (pd (D.rational :: Decode' BS.ByteString Double)) doublesC+ , bench "read double" $ nf (pd (D.read :: Decode' BS.ByteString Double)) doublesC+ , bench "float" $ nf (pd D.float) doublesC+ , bench "read float" $ nf (pd (D.read :: Decode' BS.ByteString Float)) doublesC ] doubles :: LBS.ByteString
changelog.md view
@@ -1,5 +1,9 @@ # Revision history for sv +## 1.3 -- 2019-01-14++* Update to sv-core 0.4+ ## 1.2 -- 2018-09-26 * Update to sv-core 0.3
sv.cabal view
@@ -1,5 +1,5 @@ name: sv-version: 1.2+version: 1.3 license: BSD3 license-file: LICENCE author: George Wilson@@ -76,8 +76,8 @@ tested-with: GHC == 7.10.3 , GHC == 8.0.2 , GHC == 8.2.2- , GHC == 8.4.3- , GHC == 8.6.1+ , GHC == 8.4.4+ , GHC == 8.6.3 source-repository head type: git@@ -91,14 +91,14 @@ , Data.Sv.Structure other-modules: Data.Sv.Alien.Cassava -- other-extensions: - build-depends: base >=4.8 && <5+ build-depends: base >=4.8 && < 4.13 , attoparsec >= 0.12.1.4 && < 0.14- , bifunctors >= 5.1 && < 6+ , bifunctors >= 5.1 && < 5.6 , bytestring >= 0.9.1.10 && < 0.11 , contravariant >= 1.2 && < 1.6- , hw-dsv >= 0.2.1 && < 0.3- , semigroupoids >= 5 && <6- , sv-core >= 0.3 && < 0.4+ , hw-dsv >= 0.2.1 && < 0.4+ , semigroupoids >= 5 && < 5.4+ , sv-core >= 0.4 && < 0.5 , transformers >= 0.2 && < 0.6 , utf8-string >= 1 && < 1.1 , validation >= 1 && < 1.1@@ -120,18 +120,18 @@ default-language: Haskell2010 build-depends:- base >=4.8 && <5+ base >=4.8 && < 4.13 , bytestring >= 0.9.1.10 && < 0.11 , cassava >= 0.4.1 && < 0.6 , contravariant >= 1.2 && < 1.6 , hedgehog >= 0.5 && < 0.7- , lens >= 4 && < 5+ , lens >= 4 && < 4.18 , parsers >=0.12 && <0.13 , Only >= 0.1 && < 0.2- , semigroupoids >= 5 && <6+ , semigroupoids >= 5 && < 5.4 , semigroups >= 0.18 && < 0.19 , sv- , tasty >= 0.11 && < 1.2+ , tasty >= 0.11 && < 1.3 , tasty-hedgehog >= 0.1 && < 0.3 , tasty-hunit >= 0.9 && < 0.11 , text >= 1.0 && < 1.3@@ -153,12 +153,12 @@ Haskell2010 build-depends: attoparsec >= 0.12.1.4 && < 0.14- , base >=4.8 && <5+ , base >=4.8 && < 4.13 , bytestring >= 0.9.1.10 && < 0.11 , criterion >= 1.3 && < 1.6 , deepseq >= 1.1 && < 1.5- , hw-dsv >= 0.2.1 && < 0.3- , lens >= 4 && < 5+ , hw-dsv >= 0.2.1 && < 0.4+ , lens >= 4 && < 4.18 , sv , text >= 1.0 && < 1.3 , vector >= 0.10 && < 0.13
test/Data/Sv/CassavaTest.hs view
@@ -4,13 +4,15 @@ import qualified Data.ByteString as BS import qualified Data.Csv as Csv-import Data.Sv (Validation (Failure, Success), Headedness (Unheaded), ParseOptions (_headedness), defaultParseOptions)-import qualified Data.Sv as Sv (parseDecode)+import Data.Sv (Validation (Failure, Success), Headedness (Unheaded), ParseOptions (_headedness), defaultParseOptions, defaultEncodeOptions)+import qualified Data.Sv as Sv (parseDecode, encode) import Data.Sv.Decode (Decode') import qualified Data.Sv.Decode as Sv+import Data.Sv.Encode (Encode)+import qualified Data.Sv.Encode as E import Data.Vector as V-import Data.Tuple.Only (Only (Only, fromOnly))-import Hedgehog (Gen, (===), failure, forAll, property)+import Data.Tuple.Only (Only (fromOnly))+import Hedgehog (Gen, TestLimit, (===), failure, forAll, property, withTests) import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range import Test.Tasty (TestName, TestTree, testGroup)@@ -19,24 +21,26 @@ test_CassavaAgreement :: TestTree test_CassavaAgreement = testGroup "cassava agreement"- [ cassavaAgreement "int" Sv.int (Gen.int (Range.linear (-10000000) 10000000))- , cassavaAgreement "char" Sv.char (Gen.unicode)- , cassavaAgreement "integer" Sv.integer (Gen.integral (Range.linear (-10000000) 10000000))- , cassavaAgreement "string" Sv.string (Gen.string (Range.linear 1 500) Gen.unicode)- , cassavaAgreement "bytestring" Sv.byteString (Gen.utf8 (Range.linear 1 500) Gen.unicode)- , cassavaAgreement "float" Sv.float (Gen.float (Range.exponentialFloat (-10000000) 10000000))- , cassavaAgreement "double" Sv.double (Gen.double (Range.exponentialFloat (-10000000) 10000000))+ [ cassavaAgreement "int" Sv.int E.int (Gen.int (Range.linear (-10000000) 10000000))+ , cassavaAgreement "char" Sv.char E.char (Gen.unicode)+ , cassavaAgreement "integer" Sv.integer E.integer (Gen.integral (Range.linear (-10000000) 10000000))+ , cassavaAgreement "string" Sv.string E.string (Gen.string (Range.linear 1 500) Gen.unicode)+ , cassavaAgreement' "bytestring" 5000 Sv.byteString E.byteString (Gen.utf8 (Range.linear 1 600) Gen.unicode)+ , cassavaAgreement' "float" 5000 Sv.float E.float (Gen.float (Range.exponentialFloat (-1000000000) 1000000000))+ , cassavaAgreement' "double" 5000 Sv.double E.double (Gen.double (Range.exponentialFloat (-1000000000) 1000000000)) ] opts :: ParseOptions opts = defaultParseOptions { _headedness = Unheaded } -- | Test that decoding with sv gets the same result as decoding with cassava-cassavaAgreement :: forall a . (Csv.FromField a, Csv.ToField a, Show a, Eq a) => TestName -> Decode' BS.ByteString a -> Gen a -> TestTree-cassavaAgreement name dec gen = testProperty name $ property $ do+cassavaAgreement :: forall a . (Csv.FromField a, Csv.ToField a, Show a, Eq a) => TestName -> Decode' BS.ByteString a -> Encode a -> Gen a -> TestTree+cassavaAgreement t = cassavaAgreement' t 100++cassavaAgreement' :: forall a . (Csv.FromField a, Csv.ToField a, Show a, Eq a) => TestName -> TestLimit -> Decode' BS.ByteString a -> Encode a -> Gen a -> TestTree+cassavaAgreement' name reps dec enc gen = testProperty name $ withTests reps $ property $ do a <- forAll gen- let oa = Only a- let sa = Csv.encode [oa]+ let sa = Sv.encode enc defaultEncodeOptions [a] let cassava :: Either String [a] cassava = fmap fromOnly . V.toList <$> Csv.decode Csv.NoHeader sa sv = Sv.parseDecode dec opts sa
test/Data/Sv/DecodeTest.hs view
@@ -108,7 +108,7 @@ data Semi = Semi Text Int Double Text deriving (Eq, Show) semiD :: D.Decode' ByteString Semi-semiD = Semi <$> D.utf8 <*> (parseDecoder `o` D.contents) <*> D.rational <*> D.utf8+semiD = Semi <$> D.utf8 <*> (parseDecoder `o` D.contents) <*> D.double <*> D.utf8 semigroupoidTest :: TestTree semigroupoidTest = testGroup "Semigroupoid Decode"@@ -120,7 +120,7 @@ Failure (DecodeErrors (pure (BadDecode "no"))) , testCase "Does the right thing in the case of right failure" $ parseDecode semiD opts semiTestString3 @?=- Failure (DecodeErrors (pure (BadDecode "Couldn't decode \"false\": input does not start with a digit")))+ Failure (DecodeErrors (pure (BadDecode "Couldn't decode \"false\" as a double"))) ] -- This CSV has enough columns to make an Item, it has more columns than a@@ -143,34 +143,34 @@ inOrder :: NameDecode' ByteString Item inOrder = Item <$> D.column "id" D.int <*> D.column "name" D.utf8- <*> D.column "cost" D.rational <*> D.column "units" D.int+ <*> D.column "cost" D.double <*> D.column "units" D.int outOrder :: NameDecode' ByteString Item outOrder = (\n u c i -> Item i n c u) <$> D.column "name" D.utf8- <*> D.column "units" D.int <*> D.column "cost" D.rational+ <*> D.column "units" D.int <*> D.column "cost" D.double <*> D.column "id" D.int inOrderSemi :: NameDecode' ByteString SemiItem inOrderSemi =- SemiItem <$> D.column "name" D.utf8 <*> D.column "cost" D.rational+ SemiItem <$> D.column "name" D.utf8 <*> D.column "cost" D.double outOrderSemi :: NameDecode' ByteString SemiItem2 outOrderSemi =- SemiItem2 <$> D.column "units" D.int <*> D.column "cost" D.rational+ SemiItem2 <$> D.column "units" D.int <*> D.column "cost" D.double super :: NameDecode' ByteString SuperItem super = SuperItem <$> D.column "id" D.int <*> D.column "name" D.utf8 <*> D.column "manufacturer" D.utf8- <*> D.column "cost" D.rational <*> D.column "units" D.int+ <*> D.column "cost" D.double <*> D.column "units" D.int super2 :: NameDecode' ByteString SuperItem2 super2 = SuperItem2 <$> D.column "id" D.int <*> D.column "name" D.utf8 <*> D.column "manufacturer" D.utf8- <*> D.column "cost" D.rational <*> D.column "units" D.int- <*> D.column "profit" D.rational+ <*> D.column "cost" D.double <*> D.column "units" D.int+ <*> D.column "profit" D.double namedTest :: TestTree namedTest = testGroup "Named decodes"
test/Data/Sv/EncodeTest.hs view
@@ -100,7 +100,7 @@ three :: NameEncode Three three = E.named "first" (contramap int E.int)- <> E.named "\"Second\"" (contramap double E.double)+ <> E.named "\"Second\"" (contramap double E.doubleFast) <> E.named "third" (contramap text E.text) myInt :: NameEncode Int@@ -120,8 +120,8 @@ encodeNamed three opts [] @?= "first,\"\"\"Second\"\"\",third" , testCase "multiple columns, one row" $ encodeNamed three opts [Three 1 2 "th\"ree"]- @?= "first,\"\"\"Second\"\"\",third\n1,2.0,\"th\"\"ree\""+ @?= "first,\"\"\"Second\"\"\",third\n1,2,\"th\"\"ree\"" , testCase "multiple columns, multiple rows" $ encodeNamed three opts [Three 1 2 "three", Three 4 5 "SIX"]- @?= "first,\"\"\"Second\"\"\",third\n1,2.0,three\n4,5.0,SIX"+ @?= "first,\"\"\"Second\"\"\",third\n1,2,three\n4,5,SIX" ]
test/Data/Sv/RoundTripsDecodeEncode.hs view
@@ -26,7 +26,8 @@ , integer , float , double- , rational+ , doubleFast+ , readDouble , string , byteString , lazyByteString@@ -113,13 +114,29 @@ float = roundTripCodecIso "float" D.float E.float floatingTests +doubleTests :: (IsString s, Fractional a) => [(s,a)]+doubleTests = ("7.845860130857695", 7.845860130857695) : floatingTests+ double :: TestTree double = roundTripCodecIso "double" D.double E.double- floatingTests+ ( ("1.0000000000034547e-2", 1.0000000000034547e-2)+ : doubleTests+ ) -rational :: TestTree-rational = roundTripCodecIso "rational" D.rational E.double- (("7.845860130857695", 7.845860130857695) : floatingTests)+doubleFast :: TestTree+doubleFast = roundTripCodecIso "doubleFast" D.double E.doubleFast+ [ ("5", 5)+ , ("10.5", 10.5)+ , ("12345.678", 12345.678)+ , ("7.845860130857695", 7.845860130857695)+ , ("0.010000000000034547", 1.0000000000034547e-2)+ ]++readDouble :: TestTree+readDouble = roundTripCodecIso "read double" D.read (E.show :: Encode Double)+ ( ("1.0000000000034547e-2", 1.0000000000034547e-2)+ : doubleTests+ ) text :: TestTree text = roundTripCodecIso "text" D.utf8 E.text [(utf8lb "hello", "hello"), (utf8lb "💩💩💩💩", "💩💩💩💩")]