{-# LANGUAGE RankNTypes #-} module Hedgehog.Classes.Common.Gen ( genSmallList , genVerySmallList , genSmallNonEmptyList , genShowReadPrecedence , genSmallString , genSmallInteger , genSmallSum , genCompose , genSetInteger -- * Used for 'Hedgehog.Classes.ixLaws' , genTuple , genTuple3 , genInRange , genValidRange ) where import Data.Ix (Ix(..)) import Hedgehog import Data.Functor.Compose import qualified Data.Set as S import Data.Semigroup import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range genSmallSum :: Gen (Sum Integer) genSmallSum = fmap Sum genSmallInteger genSmallInteger :: Gen Integer genSmallInteger = Gen.integral (Range.linear 0 20) genSmallNonEmptyList :: Gen a -> Gen [a] genSmallNonEmptyList gen = Gen.list (Range.linear 1 7) gen genSmallList :: Gen a -> Gen [a] genSmallList gen = Gen.list (Range.linear 0 6) gen genVerySmallList :: Gen a -> Gen [a] genVerySmallList gen = Gen.list (Range.linear 0 2) gen genSmallString :: Gen String genSmallString = Gen.string (Range.linear 0 6) Gen.ascii -- Haskell uses the operator precedences 0..9, the special function application -- precedence 10 and the precedence 11 for function arguments. Both show and -- read instances have to accept this range. According to the Haskell Language -- Report, the output of derived show instances in precedence context 11 has to -- be an atomic expression. genShowReadPrecedence :: Gen Int genShowReadPrecedence = Gen.element [0..11] genCompose :: forall f g a. Gen a -> (forall x. Gen x -> Gen (f x)) -> (forall x. Gen x -> Gen (g x)) -> Gen (Compose f g a) genCompose gen fgen ggen = Compose <$> fgen (ggen gen) genTuple :: Gen a -> Gen b -> Gen (a,b) genTuple a b = (,) <$> a <*> b genTuple3 :: Gen a -> Gen b -> Gen c -> Gen (a, b, c) genTuple3 gena genb genc = do a <- gena b <- genb c <- genc pure (a, b, c) genValidRange :: Ix a => Gen a -> Gen (a, a) genValidRange gen = do Gen.filter (\(l,u) -> l <= u) (genTuple gen gen) genInRange :: (Ix a) => Gen a -> Gen (a, a, a) genInRange gen = do Gen.filter (\(l,u,i) -> inRange (l,u) i) (genTuple3 gen gen gen) genSetInteger :: Gen (S.Set Integer) genSetInteger = do xs <- sequence $ fmap (const genSmallInteger) [1..10 :: Integer] pure $ foldMap S.singleton xs