smallcheck-series-0.7.0.0: Test/SmallCheck/Series/Instances/Internal.hs
{-# 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)