module Main (main) where
import Data.List qualified as List
import Data.Word
import Hedgehog
import Hedgehog.Gen qualified as Gen
import Hedgehog.Main
import Hedgehog.Range qualified as Range
import List.Shuffle qualified as List
import System.Random qualified as Random
main :: IO ()
main = do
defaultMain [checkParallel (Group "tests" (map (\(name, prop) -> (name, withTests 10000 (property prop))) tests))]
tests :: [(PropertyName, PropertyT IO ())]
tests =
[ ( "shuffle preserves list elements",
do
list <- generateList
gen <- generateGen
List.sort (List.shuffle_ list gen) === List.sort list
),
( "sample returns the requested number of elements",
do
list <- generateList
gen <- generateGen
n <- forAll (Gen.int (Range.linearFrom 0 (-30) (30)))
length (List.sample_ n list gen) === (min (length list) . max 0) n
),
( "sample returns a subset of list elements",
do
list <- generateList
gen <- generateGen
n <- forAll (Gen.int (Range.linearFrom 0 (-30) (30)))
assert (List.sort (List.sample_ n list gen) `isSubsetOf` List.sort list)
)
]
generateList :: PropertyT IO [Word8]
generateList =
forAll (Gen.list (Range.linear 0 200) (Gen.word8 Range.linearBounded))
generateGen :: PropertyT IO Random.StdGen
generateGen =
Random.mkStdGen <$> forAll (Gen.int Range.constantBounded)
-- precondition: lists are sorted
isSubsetOf :: (Ord a) => [a] -> [a] -> Bool
isSubsetOf [] _ = True
isSubsetOf (_ : _) [] = False
isSubsetOf (x : xs) (y : ys) =
case compare x y of
LT -> False
EQ -> isSubsetOf xs ys
GT -> isSubsetOf (x : xs) ys