Safe Haskell | None |
---|---|

Language | Haskell98 |

## Synopsis

- type Gen = GenT Identity
- newtype GenT m a = GenT {}
- class Monad m => MonadGen m where
- lift :: MonadGen m => Gen a -> m a
- shrink :: MonadGen m => (a -> [a]) -> m a -> m a
- prune :: MonadGen m => m a -> m a
- small :: MonadGen m => m a -> m a
- scale :: MonadGen m => (Size -> Size) -> m a -> m a
- resize :: MonadGen m => Size -> m a -> m a
- sized :: MonadGen m => (Size -> m a) -> m a
- integral :: (MonadGen m, Integral a) => Range a -> m a
- integral_ :: (MonadGen m, Integral a) => Range a -> m a
- int :: MonadGen m => Range Int -> m Int
- int8 :: MonadGen m => Range Int8 -> m Int8
- int16 :: MonadGen m => Range Int16 -> m Int16
- int32 :: MonadGen m => Range Int32 -> m Int32
- int64 :: MonadGen m => Range Int64 -> m Int64
- word :: MonadGen m => Range Word -> m Word
- word8 :: MonadGen m => Range Word8 -> m Word8
- word16 :: MonadGen m => Range Word16 -> m Word16
- word32 :: MonadGen m => Range Word32 -> m Word32
- word64 :: MonadGen m => Range Word64 -> m Word64
- realFloat :: (MonadGen m, RealFloat a) => Range a -> m a
- realFrac_ :: (MonadGen m, RealFrac a) => Range a -> m a
- float :: MonadGen m => Range Float -> m Float
- double :: MonadGen m => Range Double -> m Double
- enum :: (MonadGen m, Enum a) => a -> a -> m a
- enumBounded :: (MonadGen m, Enum a, Bounded a) => m a
- bool :: MonadGen m => m Bool
- bool_ :: MonadGen m => m Bool
- binit :: MonadGen m => m Char
- octit :: MonadGen m => m Char
- digit :: MonadGen m => m Char
- hexit :: MonadGen m => m Char
- lower :: MonadGen m => m Char
- upper :: MonadGen m => m Char
- alpha :: MonadGen m => m Char
- alphaNum :: MonadGen m => m Char
- ascii :: MonadGen m => m Char
- latin1 :: MonadGen m => m Char
- unicode :: MonadGen m => m Char
- unicodeAll :: MonadGen m => m Char
- string :: MonadGen m => Range Int -> m Char -> m String
- text :: MonadGen m => Range Int -> m Char -> m Text
- utf8 :: MonadGen m => Range Int -> m Char -> m ByteString
- bytes :: MonadGen m => Range Int -> m ByteString
- constant :: MonadGen m => a -> m a
- element :: MonadGen m => [a] -> m a
- choice :: MonadGen m => [m a] -> m a
- frequency :: MonadGen m => [(Int, m a)] -> m a
- recursive :: MonadGen m => ([m a] -> m a) -> [m a] -> [m a] -> m a
- discard :: MonadGen m => m a
- ensure :: MonadGen m => (a -> Bool) -> m a -> m a
- filter :: MonadGen m => (a -> Bool) -> m a -> m a
- just :: MonadGen m => m (Maybe a) -> m a
- maybe :: MonadGen m => m a -> m (Maybe a)
- list :: MonadGen m => Range Int -> m a -> m [a]
- seq :: MonadGen m => Range Int -> m a -> m (Seq a)
- nonEmpty :: MonadGen m => Range Int -> m a -> m (NonEmpty a)
- set :: (MonadGen m, Ord a) => Range Int -> m a -> m (Set a)
- map :: (MonadGen m, Ord k) => Range Int -> m (k, v) -> m (Map k v)
- freeze :: MonadGen m => m a -> m (a, m a)
- subterm :: MonadGen m => m a -> (a -> a) -> m a
- subtermM :: MonadGen m => m a -> (a -> m a) -> m a
- subterm2 :: MonadGen m => m a -> m a -> (a -> a -> a) -> m a
- subtermM2 :: MonadGen m => m a -> m a -> (a -> a -> m a) -> m a
- subterm3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> a) -> m a
- subtermM3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> m a) -> m a
- subsequence :: MonadGen m => [a] -> m [a]
- shuffle :: MonadGen m => [a] -> m [a]
- sample :: MonadIO m => Gen a -> m a
- print :: (MonadIO m, Show a) => Gen a -> m ()
- printTree :: (MonadIO m, Show a) => Gen a -> m ()
- printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m ()
- printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m ()
- runGenT :: Size -> Seed -> GenT m a -> Tree (MaybeT m) a
- mapGenT :: (Tree (MaybeT m) a -> Tree (MaybeT n) b) -> GenT m a -> GenT n b
- generate :: MonadGen m => (Size -> Seed -> a) -> m a
- liftTree :: Tree (MaybeT m) a -> GenT m a
- runDiscardEffect :: Monad m => Tree (MaybeT m) a -> Tree m (Maybe a)
- golden :: Size -> Size
- atLeast :: Int -> [a] -> Bool
- isSurrogate :: Char -> Bool
- isNoncharacter :: Char -> Bool
- data Vec n a where
- data Nat
- subtermMVec :: MonadGen m => Vec n (m a) -> (Vec n a -> m a) -> m a
- renderNodes :: (Monad m, Show a) => Size -> Seed -> Gen a -> Tree m String

# Transformer

Monad transformer which can generate random values of `a`

.

## Instances

class Monad m => MonadGen m where #

Class of monads which can generate input data for tests.

*The functions on this class can, and should, be used without their Gen*

*suffix by importing Hedgehog.Gen qualified.*

See `Gen.`

`lift`

shrinkGen :: (a -> [a]) -> m a -> m a #

See `Gen.`

`shrink`

See `Gen.`

`prune`

scaleGen :: (Size -> Size) -> m a -> m a #

See `Gen.`

`scale`

freezeGen :: m a -> m (a, m a) #

See `Gen.`

`freeze`

## Instances

MonadGen m => MonadGen (MaybeT m) # | |

Monad m => MonadGen (GenT m) # | |

MonadGen m => MonadGen (ExceptT x m) # | |

(MonadGen m, Monoid w) => MonadGen (WriterT w m) # | |

MonadGen m => MonadGen (StateT s m) # | |

MonadGen m => MonadGen (ReaderT r m) # | |

MonadGen m => MonadGen (IdentityT m) # | |

MonadGen m => MonadGen (StateT s m) # | |

(MonadGen m, Monoid w) => MonadGen (WriterT w m) # | |

(MonadGen m, Monoid w) => MonadGen (RWST r w s m) # | |

Defined in Hedgehog.Internal.Gen | |

(MonadGen m, Monoid w) => MonadGen (RWST r w s m) # | |

Defined in Hedgehog.Internal.Gen |

# Combinators

## Shrinking

shrink :: MonadGen m => (a -> [a]) -> m a -> m a #

Apply a shrinking function to a generator.

This will give the generator additional shrinking options, while keeping the existing shrinks intact.

## Size

scale :: MonadGen m => (Size -> Size) -> m a -> m a #

Adjust the size parameter by transforming it with the given function.

resize :: MonadGen m => Size -> m a -> m a #

Override the size parameter. Returns a generator which uses the given size instead of the runtime-size parameter.

sized :: MonadGen m => (Size -> m a) -> m a #

Construct a generator that depends on the size parameter.

## Integral

integral :: (MonadGen m, Integral a) => Range a -> m a #

Generates a random integral number in the given `[inclusive,inclusive]`

range.

When the generator tries to shrink, it will shrink towards the
`origin`

of the specified `Range`

.

For example, the following generator will produce a number between `1970`

and `2100`

, but will shrink towards `2000`

:

integral (Range.`constantFrom`

2000 1970 2100) ::`Gen`

`Int`

Some sample outputs from this generator might look like:

=== Outcome === 1973 === Shrinks === 2000 1987 1980 1976 1974

=== Outcome === 2061 === Shrinks === 2000 2031 2046 2054 2058 2060

integral_ :: (MonadGen m, Integral a) => Range a -> m a #

Generates a random integral number in the [inclusive,inclusive] range.

*This generator does not shrink.*

int :: MonadGen m => Range Int -> m Int #

Generates a random machine integer in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

int8 :: MonadGen m => Range Int8 -> m Int8 #

Generates a random 8-bit integer in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

int16 :: MonadGen m => Range Int16 -> m Int16 #

Generates a random 16-bit integer in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

int32 :: MonadGen m => Range Int32 -> m Int32 #

Generates a random 32-bit integer in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

int64 :: MonadGen m => Range Int64 -> m Int64 #

Generates a random 64-bit integer in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

word :: MonadGen m => Range Word -> m Word #

Generates a random machine word in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

word8 :: MonadGen m => Range Word8 -> m Word8 #

Generates a random byte in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

word16 :: MonadGen m => Range Word16 -> m Word16 #

Generates a random 16-bit word in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

word32 :: MonadGen m => Range Word32 -> m Word32 #

Generates a random 32-bit word in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

word64 :: MonadGen m => Range Word64 -> m Word64 #

Generates a random 64-bit word in the given `[inclusive,inclusive]`

range.

*This is a specialization of integral, offered for convenience.*

## Floating-point

realFloat :: (MonadGen m, RealFloat a) => Range a -> m a #

Generates a random floating-point number in the `[inclusive,exclusive)`

range.

This generator works the same as `integral`

, but for floating point numbers.

realFrac_ :: (MonadGen m, RealFrac a) => Range a -> m a #

Generates a random fractional number in the [inclusive,exclusive) range.

*This generator does not shrink.*

float :: MonadGen m => Range Float -> m Float #

Generates a random floating-point number in the `[inclusive,exclusive)`

range.

*This is a specialization of realFloat, offered for convenience.*

double :: MonadGen m => Range Double -> m Double #

Generates a random floating-point number in the `[inclusive,exclusive)`

range.

*This is a specialization of realFloat, offered for convenience.*

## Enumeration

enumBounded :: (MonadGen m, Enum a, Bounded a) => m a #

bool :: MonadGen m => m Bool #

Generates a random boolean.

This generator shrinks to `False`

.

*This is a specialization of enumBounded, offered for convenience.*

## Characters

unicode :: MonadGen m => m Char #

Generates a Unicode character, excluding noncharacters and invalid standalone surrogates:
`'\0'..'\1114111' (excluding '\55296'..'\57343')`

unicodeAll :: MonadGen m => m Char #

Generates a Unicode character, including noncharacters and invalid standalone surrogates:
`'\0'..'\1114111'`

## Strings

text :: MonadGen m => Range Int -> m Char -> m Text #

Generates a string using `Range`

to determine the length.

utf8 :: MonadGen m => Range Int -> m Char -> m ByteString #

Generates a UTF-8 encoded string, using `Range`

to determine the length.

bytes :: MonadGen m => Range Int -> m ByteString #

Generates a random `ByteString`

, using `Range`

to determine the
length.

## Choice

element :: MonadGen m => [a] -> m a #

Randomly selects one of the elements in the list.

This generator shrinks towards the first element in the list.

*The input list must be non-empty.*

choice :: MonadGen m => [m a] -> m a #

Randomly selects one of the generators in the list.

This generator shrinks towards the first generator in the list.

*The input list must be non-empty.*

frequency :: MonadGen m => [(Int, m a)] -> m a #

Uses a weighted distribution to randomly select one of the generators in the list.

This generator shrinks towards the first generator in the list.

*The input list must be non-empty.*

recursive :: MonadGen m => ([m a] -> m a) -> [m a] -> [m a] -> m a #

Modifies combinators which choose from a list of generators, like `choice`

or `frequency`

, so that they can be used in recursive scenarios.

This combinator modifies its target to select one of the generators in
either the non-recursive or the recursive list. When a selection is made
from the recursive list, the `Size`

is halved. When the `Size`

gets to one
or less, selections are no longer made from the recursive list, this
ensures termination.

A good example of where this might be useful is abstract syntax trees:

data Expr = Var String | Lam String Expr | App Expr Expr -- Assuming we have a name generator genName ::`MonadGen`

m => m String -- We can write a generator for expressions genExpr ::`MonadGen`

m => m Expr genExpr = Gen.`recursive`

Gen.`choice`

[ -- non-recursive generators Var`<$>`

genName ] [ -- recursive generators Gen.`subtermM`

genExpr (x -> Lam`<$>`

genName`<*>`

pure x) , Gen.`subterm2`

genExpr genExpr App ]

If we wrote the above example using only `choice`

, it is likely that it
would fail to terminate. This is because for every call to `genExpr`

,
there is a 2 in 3 chance that we will recurse again.

## Conditional

ensure :: MonadGen m => (a -> Bool) -> m a -> m a #

Discards the generator if the generated value does not satisfy the predicate.

filter :: MonadGen m => (a -> Bool) -> m a -> m a #

Generates a value that satisfies a predicate.

This is essentially:

filter p gen =`mfilter`

p gen`<|>`

filter p gen

It differs from the above in that we keep some state to avoid looping forever. If we trigger these limits then the whole generator is discarded.

## Collections

list :: MonadGen m => Range Int -> m a -> m [a] #

Generates a list using a `Range`

to determine the length.

seq :: MonadGen m => Range Int -> m a -> m (Seq a) #

Generates a seq using a `Range`

to determine the length.

nonEmpty :: MonadGen m => Range Int -> m a -> m (NonEmpty a) #

Generates a non-empty list using a `Range`

to determine the length.

set :: (MonadGen m, Ord a) => Range Int -> m a -> m (Set a) #

Generates a set using a `Range`

to determine the length.

*This may fail to generate anything if the element generator*
*cannot produce a large enough number of unique items to satify*
*the required set size.*

map :: (MonadGen m, Ord k) => Range Int -> m (k, v) -> m (Map k v) #

Generates a map using a `Range`

to determine the length.

*This may fail to generate anything if the keys produced by the*
*generator do not account for a large enough number of unique*
*items to satify the required map size.*

## Subterms

freeze :: MonadGen m => m a -> m (a, m a) #

Freeze the size and seed used by a generator, so we can inspect the value which it will produce.

This is used for implementing `list`

and `subtermMVec`

. It allows us to
shrink the list itself before trying to shrink the values inside the list.

subterm :: MonadGen m => m a -> (a -> a) -> m a #

Constructs a generator from a sub-term generator.

*Shrinks to the sub-term if possible.*

subtermM :: MonadGen m => m a -> (a -> m a) -> m a #

Constructs a generator from a sub-term generator.

*Shrinks to the sub-term if possible.*

subterm2 :: MonadGen m => m a -> m a -> (a -> a -> a) -> m a #

Constructs a generator from two sub-term generators.

*Shrinks to one of the sub-terms if possible.*

subtermM2 :: MonadGen m => m a -> m a -> (a -> a -> m a) -> m a #

Constructs a generator from two sub-term generators.

*Shrinks to one of the sub-terms if possible.*

subterm3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> a) -> m a #

Constructs a generator from three sub-term generators.

*Shrinks to one of the sub-terms if possible.*

subtermM3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> m a) -> m a #

Constructs a generator from three sub-term generators.

*Shrinks to one of the sub-terms if possible.*

## Combinations & Permutations

subsequence :: MonadGen m => [a] -> m [a] #

Generates a random subsequence of a list.

shuffle :: MonadGen m => [a] -> m [a] #

Generates a random permutation of a list.

This shrinks towards the order of the list being identical to the input list.

# Sampling Generators

print :: (MonadIO m, Show a) => Gen a -> m () #

Run a generator with a random seed and print the outcome, and the first level of shrinks.

`Gen.print (Gen.``enum`

'a' 'f')

=== Outcome === 'd' === Shrinks === 'a' 'b' 'c'

printTree :: (MonadIO m, Show a) => Gen a -> m () #

Run a generator with a random seed and print the resulting shrink tree.

`Gen.printTree (Gen.``enum`

'a' 'f')

'd' ├╼'a' ├╼'b' │ └╼'a' └╼'c' ├╼'a' └╼'b' └╼'a'

*This may not terminate when the tree is very large.*

printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m () #

Print the value produced by a generator, and the first level of shrinks, for the given size and seed.

Use `print`

to generate a value from a random seed.

printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m () #

Print the shrink tree produced by a generator, for the given size and seed.

Use `printTree`

to generate a value from a random seed.

# Internal

These functions are exported in case you need them in a pinch, but are not part of the public API and may change at any time, even as part of a minor update.

## Transfomer

runGenT :: Size -> Seed -> GenT m a -> Tree (MaybeT m) a #

Runs a generator, producing its shrink tree.

mapGenT :: (Tree (MaybeT m) a -> Tree (MaybeT n) b) -> GenT m a -> GenT n b #

Map over a generator's shrink tree.

liftTree :: Tree (MaybeT m) a -> GenT m a #

Lift a predefined shrink tree in to a generator, ignoring the seed and the size.

## Size

Scale a size using the golden ratio.

golden x = x / φ golden x = x / 1.61803..

## Shrinking

## Characters

isSurrogate :: Char -> Bool #

Check if a character is in the surrogate category.

isNoncharacter :: Char -> Bool #

Check if a character is one of the noncharacters '\65534', '\65535'.

## Subterms

## Instances

Functor (Vec n) # | |

Foldable (Vec n) # | |

Defined in Hedgehog.Internal.Gen fold :: Monoid m => Vec n m -> m # foldMap :: Monoid m => (a -> m) -> Vec n a -> m # foldr :: (a -> b -> b) -> b -> Vec n a -> b # foldr' :: (a -> b -> b) -> b -> Vec n a -> b # foldl :: (b -> a -> b) -> b -> Vec n a -> b # foldl' :: (b -> a -> b) -> b -> Vec n a -> b # foldr1 :: (a -> a -> a) -> Vec n a -> a # foldl1 :: (a -> a -> a) -> Vec n a -> a # elem :: Eq a => a -> Vec n a -> Bool # maximum :: Ord a => Vec n a -> a # minimum :: Ord a => Vec n a -> a # | |

Traversable (Vec n) # | |

subtermMVec :: MonadGen m => Vec n (m a) -> (Vec n a -> m a) -> m a #

Constructs a generator from a number of sub-term generators.

*Shrinks to one of the sub-terms if possible.*