constrained-generators-0.2.0.0: examples/Constrained/Examples/Map.hs
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ViewPatterns #-}
module Constrained.Examples.Map where
import Constrained.API
import Constrained.Examples.Basic
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Set (Set)
import Data.Set qualified as Set
import Data.Word
mapElemSpec :: Specification (Map Int (Bool, Int))
mapElemSpec = constrained $ \m ->
[ assert $ m /=. lit mempty
, forAll' (rng_ m) $ \_ b ->
[0 <. b, b <. 10]
]
mapPairSpec :: Specification (Map Int Int, Set Int)
mapPairSpec = constrained' $ \m s ->
subset_ (dom_ m) s
mapEmptyDomainSpec :: Specification (Map Int Int)
mapEmptyDomainSpec = constrained $ \m ->
subset_ (dom_ m) mempty -- mempty in the Monoid instance (Term fn (Set a))
mapSubSize :: Specification (Map Int Int)
mapSubSize = constrained $ \s ->
2 ==. 12 - (sizeOf_ s)
knownDomainMap :: Specification (Map Int Int)
knownDomainMap = constrained $ \m ->
[ dom_ m ==. lit (Set.fromList [1, 2])
, not_ $ 0 `elem_` rng_ m
]
mapSizeConstrained :: Specification (Map Three Int)
mapSizeConstrained = constrained $ \m -> sizeOf_ m <=. 3
sumRange :: Specification (Map Word64 Word64)
sumRange = constrained $ \m -> sum_ (rng_ m) ==. lit 10
fixedRange :: Specification (Map Int Int)
fixedRange = constrained $ \m ->
[ forAll (rng_ m) (\x -> x ==. 5)
, assert $ (sizeOf_ m) ==. 1
]
rangeHint :: Specification (Map Int Int)
rangeHint = constrained $ \m ->
genHint 10 (rng_ m)
rangeSumSize :: Specification (Map Int Int)
rangeSumSize = constrained $ \m ->
[ assert $ sizeOf_ m <=. 0
, assert $ sum_ (rng_ m) <=. 0
, assert $ (-1) <=. sum_ (rng_ m)
, forAll' m $ \k v ->
[ k ==. (-1)
, v ==. 1
]
]
elemSpec :: Specification (Int, Int, Map Int Int)
elemSpec = constrained' $ \ [var|key|] [var|val|] [var|mapp|] ->
[ assert $ key `member_` dom_ mapp
, forAll' mapp $ \ [var|k'|] [var|v'|] ->
whenTrue (k' ==. key) (v' ==. val)
, mapp `dependsOn` key
]
lookupSpecific :: Specification (Int, Int, Map Int Int)
lookupSpecific = constrained' $ \ [var|k|] [var|v|] [var|m|] ->
[ m `dependsOn` k
, assert $ lookup_ k m ==. just_ v
]
mapRestrictedValues :: Specification (Map (Either Int ()) Int)
mapRestrictedValues = constrained $ \m ->
[ assert $ sizeOf_ m ==. 6
, forAll' m $ \k v ->
[ caseOn
k
(branch $ \_ -> 20 <=. v)
(branch $ \_ -> True)
, v `dependsOn` k
]
]
-- NOTE: this fails if you pick the values of the map first - you're unlikely to generate
-- three values such that two of them are <= -100 and >= 100 respectively even though
-- you take satisfiability of the whole elem constraint into account. This can't be fixed
-- with a `dependsOn v k` because the issue is that we've generated a bunch of values
-- before we ever go to generate the keys.
mapRestrictedValuesThree :: Specification (Map Three Int)
mapRestrictedValuesThree = constrained $ \m ->
[ assert $ sizeOf_ m ==. 3
, forAll' m $ \k v ->
[ caseOn
k
(branch $ \_ -> v <=. (-100))
(branch $ \_ -> 100 <=. v)
(branch $ \_ -> True)
, -- This is important to demonstrate the point that keys sometimes need to be solved before
-- values
v `dependsOn` k
]
]
mapRestrictedValuesBool :: Specification (Map Bool Int)
mapRestrictedValuesBool = constrained $ \m ->
[ assert $ sizeOf_ m ==. 2
, forAll' m $ \k v -> [v `dependsOn` k, whenTrue k (100 <=. v)]
]
mapSetSmall :: Specification (Map (Set Int) Int)
mapSetSmall = constrained $ \x ->
forAll (dom_ x) $ \d ->
assert $ subset_ d $ lit (Set.fromList [3 .. 4])
-- | this tests the function saturatePred
mapIsJust :: Specification (Int, Int)
mapIsJust = constrained' $ \ [var| x |] [var| y |] ->
just_ x ==. lookup_ y (lit $ Map.fromList [(z, z) | z <- [100 .. 102]])
eitherKeys :: Specification ([Int], [Int], Map (Either Int Int) Int)
eitherKeys = constrained' $ \ [var| as |] [var| bs |] [var| m |] ->
[ forAll' m $ \ [var| k |] _v ->
[ caseOn
k
(branch $ \a -> a `elem_` as)
(branch $ \b -> b `elem_` bs)
, reify as (map Left) $ \ls ->
reify bs (map Right) $ \rs ->
k `elem_` ls ++. rs
]
]
keysExample :: Specification (Either Int Int)
keysExample = constrained $ \k ->
[ caseOn
k
(branch $ \a -> a `elem_` as)
(branch $ \b -> b `elem_` bs)
, reify as (map Left) $ \ls ->
reify bs (map Right) $ \rs ->
k `elem_` ls ++. rs
]
where
as = lit [1 .. 10]
bs = lit [11 .. 20]
failingKVSpec :: Specification (Map Int Int)
failingKVSpec = constrained $ \m ->
[ assert $ 10 <. sizeOf_ m
, forAll' m $ \k _v ->
k `satisfies` chooseSpec (1, constrained $ \k' -> 2 * k' ==. 1) (3, mempty)
]