| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Generic.Random.Internal.Generic
Contents
- genericArbitrary :: (Generic a, GA Unsized (Rep a)) => Gen a
- genericArbitraryFrequency :: (Generic a, GA Unsized (Rep a)) => [Int] -> Gen a
- genericArbitraryFrequency' :: forall n a. (Generic a, GA (Sized n) (Rep a)) => [Int] -> Gen a
- genericArbitrary' :: forall n a. (Generic a, GA (Sized n) (Rep a)) => Gen a
- newtype Freq sized a = Freq {}
- newtype Gen' sized a = Gen' {}
- data Sized :: Nat -> *
- data Unsized
- liftGen :: Gen a -> Freq sized a
- class GA sized f where
- gArbitrarySingle :: forall sized f p. GA sized f => Gen' sized (f p)
- class GASum sized f where
- class GAProduct f where
- newtype Tagged a b = Tagged {
- unTagged :: b
- data Nat
- class BaseCases n f where
- type BaseCases' n a = (Generic a, BaseCases n (Rep a))
- baseCases' :: forall n f p. BaseCases n f => Tagged n [f p]
Random generators
genericArbitrary :: (Generic a, GA Unsized (Rep a)) => Gen a Source #
Pick a constructor with uniform probability, and fill its fields recursively.
An equivalent definition for Tree is:
genericArbitrary :: Arbitrary a => Gen (Tree a)
genericArbitrary =
oneof
[ Leaf <$> arbitrary -- Uses Arbitrary a
, Node <$> arbitrary <*> arbitrary -- Uses Arbitrary (Tree a)
]Note that for many types, genericArbitrary tends to produce big values.
For instance for Tree a values are finite but the average number of
Leaf and Node constructors is infinite.
genericArbitraryFrequency Source #
This allows to specify the probability distribution of constructors as a list of weights, in the same order as the data type definition.
An equivalent definition for Tree is:
genericArbitraryFrequency :: Arbitrary a => [Int] -> Gen (Tree a)
genericArbitraryFrequency [x, y] =
frequency
[ (x, Leaf <$> arbitrary)
, (y, Node <$> arbitrary <*> arbitrary)
]genericArbitraryFrequency' Source #
Arguments
| :: forall (n :: Nat). (Generic a, GA (Sized n) (Rep a)) | |
| => [Int] | List of weights for every constructor |
| -> Gen a |
The size parameter of Gen is divided among the fields of the chosen
constructor. When it reaches zero, the generator selects a finite term
whenever it can find any of the given type.
The type of genericArbitraryFrequency' has an ambiguous n parameter; it
is a type-level natural number of type Nat. That number determines the
maximum depth of terms that can be used to end recursion.
You'll need the TypeApplications and DataKinds extensions.
genericArbitraryFrequency' @n weights
With n ~ ', the generator looks for a simple nullary constructor. If none
exist at the current type, as is the case for our ZTree type, it carries on
as in genericArbitraryFrequency.
genericArbitraryFrequency' @'Z :: Arbitrary a => [Int] -> Gen (Tree a)
genericArbitraryFrequency' @'Z [x, y] =
frequency
[ (x, Leaf <$> arbitrary)
, (y, scale (`div` 2) $ Node <$> arbitrary <*> arbitrary)
]
-- 2 because Node is 2-ary.Here is another example:
data Tree' = Leaf1 | Leaf2 | Node3 Tree' Tree' Tree' deriving Generic instance Arbitrary Tree' where arbitrary = genericArbitraryFrequency' @'Z [1, 2, 3]
genericArbitraryFrequency' is equivalent to:
genericArbitraryFrequency' @'Z :: [Int] -> Gen Tree'
genericArbitraryFrequency' @'Z [x, y, z] =
sized $ \n ->
if n == 0 then
-- If the size parameter is zero, the non-nullary alternative is discarded.
frequency $
[ (x, return Leaf1)
, (y, return Leaf2)
]
else
frequency $
[ (x, return Leaf1)
, (y, return Leaf2)
, (z, resize (n `div` 3) node)
]
-- 3 because Node3 is 3-ary
where
node = Node3 <$> arbitrary <*> arbitrary <*> arbitraryTo increase the chances of termination when no nullary constructor is directly
available, such as in Tree, we can pass a larger depth n. The effectiveness
of this parameter depends on the concrete type the generator is used for.
For instance, if we want to generate a value of type Tree (), there is a
value of depth 1 (represented by ') that we can use to end
recursion: S 'ZLeaf ().
genericArbitraryFrequency' @('S 'Z) :: [Int] -> Gen (Tree ())
genericArbitraryFrequency' @('S 'Z) [x, y] =
sized $ \n ->
if n == 0 then
return (Leaf ())
else
frequency
[ (x, Leaf <$> arbitrary)
, (y, scale (`div` 2) $ Node <$> arbitrary <*> arbitrary)
]Because the argument of Tree must be inspected in order to discover
values of type Tree (), we incur some extra constraints if we want
polymorphism.
FlexibleContexts and UndecidableInstances are also required.
instance (Arbitrary a, Generic a, BaseCases 'Z (Rep a))
=> Arbitrary (Tree a) where
arbitrary = genericArbitraryFrequency' @('S 'Z) [1, 2]A synonym is provided for brevity.
instance (Arbitrary a, BaseCases' 'Z a) => Arbitrary (Tree a) where
arbitrary = genericArbitraryFrequency' @('S 'Z) [1, 2]genericArbitrary' :: forall n a. (Generic a, GA (Sized n) (Rep a)) => Gen a Source #
Like genericArbitraryFrequency', but with uniformly distributed
constructors.
Internal
class GA sized f where Source #
Generic Arbitrary
Minimal complete definition
Instances
| GA sized U1 Source # | |
| Arbitrary c => GA sized (K1 i c) Source # | |
| (GASum Unsized f, GASum Unsized g) => GA Unsized ((:+:) f g) Source # | |
| (GA Unsized f, GA Unsized g) => GA Unsized ((:*:) f g) Source # | |
| GA sized f => GA sized (M1 i c f) Source # | |
| (GAProduct f, GAProduct g) => GA (Sized n) ((:*:) f g) Source # | |
| (GASum (Sized n) f, GASum (Sized n) g, BaseCases n f, BaseCases n g) => GA (Sized n) ((:+:) f g) Source # | |
gArbitrarySingle :: forall sized f p. GA sized f => Gen' sized (f p) Source #
class BaseCases n f where Source #
A BaseCases n ( constraint basically provides the list of values
of type Rep a)a with depth at most n.
Minimal complete definition
Instances
| BaseCases n U1 Source # | |
| (BaseCases n f, BaseCases n g) => BaseCases n ((:*:) f g) Source # | |
| (BaseCases n f, BaseCases n g) => BaseCases n ((:+:) f g) Source # | |
| BaseCases Z (K1 i c) Source # | |
| BaseCases n f => BaseCases n (M1 i c f) Source # | |
| (Generic c, BaseCases n (Rep c)) => BaseCases (S n) (K1 i c) Source # | |
baseCases' :: forall n f p. BaseCases n f => Tagged n [f p] Source #