smallcheck-series 0.6.1.1 → 0.7.0.0
raw patch · 5 files changed
+75/−2 lines, 5 filesdep +smallcheck-seriesdep +tastydep +tasty-hunitdep ~basedep ~smallcheckPVP ok
version bump matches the API change (PVP)
Dependencies added: smallcheck-series, tasty, tasty-hunit, tasty-smallcheck
Dependency ranges changed: base, smallcheck
API changes (from Hackage documentation)
+ Test.SmallCheck.Series.Instances: instance (GHC.Num.Num a, GHC.Classes.Ord a, Test.SmallCheck.Series.Serial m a, Test.SmallCheck.Series.Serial Data.Functor.Identity.Identity a) => Test.SmallCheck.Series.Serial m (Data.Set.Internal.Set a)
+ Test.SmallCheck.Series.Instances.Internal: binaryExpansion :: Word -> [Bool]
+ Test.SmallCheck.Series.Instances.Internal: sets :: (Ord a, Serial m a, Serial Identity a) => Series m [a]
Files
- CHANGELOG.md +4/−0
- Test/SmallCheck/Series/Instances.hs +9/−1
- Test/SmallCheck/Series/Instances/Internal.hs +33/−0
- smallcheck-series.cabal +9/−1
- tests/Main.hs +20/−0
CHANGELOG.md view
@@ -4,6 +4,10 @@ CHANGELOG](http://keepachangelog.com/). This project adheres to [Semantic Versioning](http://semver.org/). +## [0.7.0.0] — Tuesday, 15 of September 2020+### Added+- An instance `Serial` for `Set`.+ ## [0.6.1.1] - Tuesday, 15 of September 2020 ### Fixed - Allow `base` versions up to `4.15`.
Test/SmallCheck/Series/Instances.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiWayIf #-} {-# OPTIONS_GHC -fno-warn-orphans #-}@@ -20,6 +21,7 @@ * 'Data.Text.Text' * 'Data.Text.Lazy.Text' * 'Data.Text.Lazy.Text'+* 'Data.Set.Set' * 'Data.Map.Map' By default the most exhaustive series are provided which can lead to@@ -42,6 +44,9 @@ import Data.Int import Data.Word #endif+import Data.Functor.Identity (Identity)+import qualified Data.Set as Set+import Data.Set (Set) import qualified Data.Map as Map import Data.Map (Map) import qualified Data.ByteString as B@@ -49,7 +54,7 @@ import qualified Data.Text as T import qualified Data.Text.Lazy as TL import Test.SmallCheck.Series-+import Test.SmallCheck.Series.Instances.Internal #if !MIN_VERSION_smallcheck(1,1,4) instance Monad m => Serial m Int8 where series = ints@@ -150,6 +155,9 @@ return $ \bs -> case TL.uncons bs of Nothing -> y Just (b,bs') -> f (TL.singleton b) bs'++instance (Num a, Ord a, Serial m a, Serial Identity a) => Serial m (Set a) where+ series = fmap Set.fromList sets instance (Serial m k, Serial m v) => Serial m (Map k v) where series = Map.singleton <$> series <~> series
+ Test/SmallCheck/Series/Instances/Internal.hs view
@@ -0,0 +1,33 @@+{-# language FlexibleContexts #-}+{-# language CPP #-}++module Test.SmallCheck.Series.Instances.Internal where++import Test.SmallCheck.Series+import Data.Functor.Identity+#if !MIN_VERSION_base(4,8,0)+import Data.Word (Word)+#endif++sets :: (Ord a, Serial m a, Serial Identity a) => Series m [a]+sets = do+ depth <- getDepth+ let xs = list depth series -- We are going to generate all subsets of this enumeration.+ i <- localDepth (const (2^min depth (length xs) - 1)) series+ -- This complicated expression ensures that a number is chosen from just a+ -- large enough subset of `Word`.+ -- - For finite types, the enumeration `xs` can inherently be no longer than+ -- their cardinality.+ -- - For infinite types, we make sure that `i` has at most `depth` binary+ -- digits.+ -- For the depth of −1 the series for `Word` is empty, and for depth n > 0+ -- it equals {0… n}. So, we adjust depth by −1 to make sure there are+ -- exactly `depth` elements: |{0… n−1}| = n.++ let pattern = binaryExpansion i+ ys = snd . unzip . filter fst . zip pattern $ xs+ return ys++binaryExpansion :: Word -> [Bool]+binaryExpansion 0 = [ ]+binaryExpansion i = ((i `mod` 2) == 1): binaryExpansion (i `div` 2)
smallcheck-series.cabal view
@@ -1,5 +1,5 @@ name: smallcheck-series-version: 0.6.1.1+version: 0.7.0.0 synopsis: Extra SmallCheck series and utilities description: Orphan@@ -29,6 +29,7 @@ exposed-modules: Test.SmallCheck.Series.ByteString Test.SmallCheck.Series.ByteString.Lazy Test.SmallCheck.Series.Instances+ Test.SmallCheck.Series.Instances.Internal Test.SmallCheck.Series.Text Test.SmallCheck.Series.Text.Lazy Test.SmallCheck.Series.Utils@@ -49,3 +50,10 @@ build-depends: base >=4.6 && <4.15, Glob >=0.7.5, doctest >=0.9.10++test-suite checks+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: Main.hs+ build-depends: base, smallcheck, smallcheck-series, tasty, tasty-smallcheck, tasty-hunit
+ tests/Main.hs view
@@ -0,0 +1,20 @@+module Main where++import qualified Data.List as List+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.SmallCheck+import Test.SmallCheck.Series+import Test.SmallCheck.Series.Instances.Internal++main :: IO ( )+main = defaultMain $ testGroup "Verify `sets`."+ [ testGroup "An element is present in a set at most once"+ [ testProperty "Int" $ over sets $ \xs -> (xs :: [Int]) == List.nub xs+ , testProperty "Bool" $ over sets $ \xs -> (xs :: [Bool]) == List.nub xs+ ]+ , testProperty "All possible sets within depth limit are generated (for a large enough type)"+ $ \(NonNegative n) -> length (list n sets :: [[Int]]) == 2^n+ , testCase "All 4 sets of depth 2 are generated"+ $ assertEqual "" [[ ], [0], [1], [0, 1]] (list 2 sets :: [[Int]])+ ]