-- | "GHC.Generics"-based 'Test.QuickCheck.arbitrary' generators. -- -- = Basic usage -- -- @ -- {-\# LANGUAGE DeriveGeneric \#-} -- -- data Foo = A | B | C -- some generic data type -- deriving 'GHC.Generics.Generic' -- @ -- -- Derive instances of 'Test.QuickCheck.Arbitrary'. -- -- @ -- instance Arbitrary Foo where -- arbitrary = 'genericArbitrary' 'uniform' -- Give a distribution of constructors. -- shrink = 'Test.QuickCheck.genericShrink' -- Generic shrinking is provided by the QuickCheck library. -- @ -- -- Or derive standalone generators (the fields must still be instances of -- 'Test.QuickCheck.Arbitrary', or use custom generators). -- -- @ -- genFoo :: Gen Foo -- genFoo = 'genericArbitrary' 'uniform' -- @ -- -- === Using @DerivingVia@ -- -- @ -- {-\# LANGUAGE DerivingVia, TypeOperators \#-} -- -- data Foo = A | B | C -- deriving 'GHC.Generics.Generic' -- deriving Arbitrary via ('GenericArbitraryU' `'AndShrinking'` Foo) -- @ -- -- For more information: -- -- - "Generic.Random.Tutorial" -- - http://blog.poisson.chat/posts/2018-01-05-generic-random-tour.html {-# LANGUAGE ExplicitNamespaces #-} module Generic.Random ( -- * Arbitrary implementations -- | The suffixes for the variants have the following meanings: -- -- - @U@: pick constructors with uniform distribution (equivalent to -- passing 'uniform' to the non-@U@ variant). -- - @Single@: restricted to types with a single constructor. -- - @G@: with custom generators. -- - @Rec@: decrease the size at every recursive call (ensuring termination -- for (most) recursive types). -- - @'@: automatic discovery of "base cases" when size reaches 0. genericArbitrary , genericArbitraryU , genericArbitrarySingle , genericArbitraryRec , genericArbitrary' , genericArbitraryU' -- ** With custom generators -- | -- === Note about incoherence -- -- The custom generator feature relies on incoherent instances, which can -- lead to surprising behaviors for parameterized types. -- -- ==== __Example__ -- -- For example, here is a pair type and a custom generator of @Int@ (always -- generating 0). -- -- @ -- data Pair a b = Pair a b -- deriving (Generic, Show) -- -- customGen :: Gen Int -- customGen = pure 0 -- @ -- -- The following two ways of defining a generator of @Pair Int Int@ are -- __not__ equivalent. -- -- The first way is to use 'genericArbitrarySingleG' to define a -- @Gen (Pair a b)@ parameterized by types @a@ and @b@, and then -- specialize it to @Gen (Pair Int Int)@. -- -- In this case, the @customGen@ will be ignored. -- -- @ -- genPair :: (Arbitrary a, Arbitrary b) => Gen (Pair a b) -- genPair = 'genericArbitrarySingleG' customGen -- -- genPair' :: Gen (Pair Int Int) -- genPair' = genPair -- -- Will generate nonzero pairs -- @ -- -- The second way is to define @Gen (Pair Int Int)@ directly using -- 'genericArbitrarySingleG' (as if we inlined @genPair@ in @genPair'@ -- above. -- -- Then the @customGen@ will actually be used. -- -- @ -- genPair2 :: Gen (Pair Int Int) -- genPair2 = 'genericArbitrarySingleG' customGen -- -- Will only generate (Pair 0 0) -- @ -- -- In other words, the decision of whether to use a custom generator -- is done by comparing the type of the custom generator with the type of -- the field only in the context where 'genericArbitrarySingleG' is being -- used (or any other variant with a @G@ suffix). -- -- In the first case above, those fields have types @a@ and @b@, which are -- not equal to @Int@ (or rather, there is no available evidence that they -- are equal to @Int@, even if they could be instantiated as @Int@ later). -- In the second case, they both actually have type @Int@. , genericArbitraryG , genericArbitraryUG , genericArbitrarySingleG , genericArbitraryRecG -- * Specifying finite distributions , Weights , W , (%) , uniform -- * Custom generators -- | Custom generators can be specified in a list constructed with @(':+')@, -- and passed to functions such as 'genericArbitraryG' to override how certain -- fields are generated. -- -- Example: -- -- @ -- customGens :: Gen String ':+' Gen Int -- customGens = -- (filter (/= '\NUL') '<$>' arbitrary) ':+' -- (getNonNegative '<$>' arbitrary) -- @ -- -- There are also different types of generators, other than 'Test.QuickCheck.Gen', providing -- more ways to select the fields the generator than by simply comparing types: -- -- - @'Test.QuickCheck.Gen' a@: override fields of type @a@; -- - @'Gen1' f@: override fields of type @f x@ for some @x@, requiring a generator for @x@; -- - @'Gen1_' f@: override fields of type @f x@ for some @x@, __not__ requiring a generator for @x@; -- - @'FieldGen' s a@: override record fields named @s@, which must have type @a@; -- - @'ConstrGen' c i a@: override the field at index @i@ of constructor @c@, -- which must have type @a@ (0-indexed); -- -- Multiple generators may match a given field: the first, leftmost -- generator in the list will be chosen. , (:+) (..) , FieldGen (..) , fieldGen , ConstrGen (..) , constrGen , Gen1 (..) , Gen1_ (..) -- * Helpful combinators , listOf' , listOf1' , vectorOf' -- * Base cases for recursive types , withBaseCase , BaseCase (..) -- * Full options , Options () , genericArbitraryWith -- ** Setters , SetOptions , type (<+) , setOpts -- ** Size modifiers , Sizing (..) , SetSized , SetUnsized , setSized , setUnsized -- ** Custom generators , SetGens , setGenerators -- ** Coherence options , Coherence (..) , Incoherent (..) -- ** Common options , SizedOpts , sizedOpts , SizedOptsDef , sizedOptsDef , UnsizedOpts , unsizedOpts -- *** Advanced options -- | See 'Coherence' , CohUnsizedOpts , cohUnsizedOpts , CohSizedOpts , cohSizedOpts -- * Generic classes , GArbitrary , GUniformWeight -- * Newtypes for DerivingVia -- | These newtypes correspond to the variants of 'genericArbitrary' above. , GenericArbitrary (..) , GenericArbitraryU (..) , GenericArbitrarySingle (..) , GenericArbitraryRec (..) , GenericArbitraryG (..) , GenericArbitraryUG (..) , GenericArbitrarySingleG (..) , GenericArbitraryRecG (..) , GenericArbitraryWith (..) , AndShrinking (..) -- ** Helpers typeclasses , TypeLevelGenList (..) , TypeLevelOpts (..) ) where import Generic.Random.Internal.BaseCase import Generic.Random.Internal.Generic import Generic.Random.DerivingVia