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

Language | Haskell2010 |

## Synopsis

- type Gen = GenT Identity
- newtype GenT m a = GenT {}
- class (Monad m, Monad (GenBase m)) => MonadGen m where
- generalize :: Monad m => Gen a -> GenT 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, GenBase m ~ Identity) => (a -> Bool) -> m a -> m a
- mapMaybe :: (MonadGen m, GenBase m ~ Identity) => (a -> Maybe b) -> m a -> m b
- filterT :: MonadGen m => (a -> Bool) -> m a -> m a
- mapMaybeT :: MonadGen m => (a -> Maybe b) -> m a -> m b
- just :: (MonadGen m, GenBase m ~ Identity) => m (Maybe a) -> m a
- justT :: MonadGen m => m (Maybe a) -> m a
- maybe :: MonadGen m => m a -> m (Maybe a)
- either :: MonadGen m => m a -> m b -> m (Either a b)
- either_ :: MonadGen m => m a -> m b -> m (Either a b)
- 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]
- shuffleSeq :: MonadGen m => Seq a -> m (Seq 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 ()
- renderTree :: Show a => Size -> Seed -> Gen a -> String
- runGenT :: Size -> Seed -> GenT m a -> TreeT (MaybeT m) a
- evalGen :: Size -> Seed -> Gen a -> Maybe (Tree a)
- evalGenT :: Monad m => Size -> Seed -> GenT m a -> TreeT m (Maybe a)
- mapGenT :: (TreeT (MaybeT m) a -> TreeT (MaybeT n) b) -> GenT m a -> GenT n b
- generate :: MonadGen m => (Size -> Seed -> a) -> m a
- toTree :: forall m a. (MonadGen m, GenBase m ~ Identity) => m a -> m (Tree a)
- toTreeMaybeT :: MonadGen m => m a -> m (TreeT (MaybeT (GenBase m)) a)
- fromTree :: MonadGen m => Tree a -> m a
- fromTreeT :: MonadGen m => TreeT (GenBase m) a -> m a
- fromTreeMaybeT :: MonadGen m => TreeT (MaybeT (GenBase m)) a -> m a
- runDiscardEffect :: TreeT (MaybeT Identity) a -> Maybe (Tree a)
- runDiscardEffectT :: Monad m => TreeT (MaybeT m) a -> TreeT 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

# Transformer

Monad transformer which can generate random values of `a`

.

#### Instances

class (Monad m, Monad (GenBase m)) => MonadGen m where Source #

Class of monads which can generate input data for tests.

#### Instances

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

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

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

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

MonadGen m => MonadGen (StateT r m) Source # | |

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

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

MonadGen m => MonadGen (StateT r m) Source # | |

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

# Combinators

generalize :: Monad m => Gen a -> GenT m a Source #

Lift a `Gen / GenT Identity`

in to a `Monad m => GenT m`

## Shrinking

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

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 Source #

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

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

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 Source #

Construct a generator that depends on the size parameter.

## Integral

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

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 Source #

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

*This generator does not shrink.*

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

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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

*This generator does not shrink.*

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

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 Source #

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

range.

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

## Enumeration

bool :: MonadGen m => m Bool Source #

Generates a random boolean.

This generator shrinks to `False`

.

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

## Characters

alphaNum :: MonadGen m => m Char Source #

Generates an ASCII letter or digit: `'a'..'z', 'A'..'Z', '0'..'9'`

unicode :: MonadGen m => m Char Source #

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

unicodeAll :: MonadGen m => m Char Source #

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

## Strings

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

Generates a string using `Range`

to determine the length.

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

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

to determine the length.

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

Generates a random `ByteString`

, using `Range`

to determine the
length.

## Choice

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

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 Source #

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 Source #

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 Source #

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 Source #

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

filter :: (MonadGen m, GenBase m ~ Identity) => (a -> Bool) -> m a -> m a Source #

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

either :: MonadGen m => m a -> m b -> m (Either a b) Source #

Generates either an `a`

or a `b`

.

As the size grows, this generator generates `Right`

s more often than `Left`

s.

either_ :: MonadGen m => m a -> m b -> m (Either a b) Source #

Generates either an `a`

or a `b`

, without bias.

This generator generates as many `Right`

s as it does `Left`

s.

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

Generates a list using a `Range`

to determine the length.

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

Generates a seq using a `Range`

to determine the length.

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

Generates a non-empty list using a `Range`

to determine the length.

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

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) Source #

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) Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

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] Source #

Generates a random subsequence of a list.

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

Generates a random permutation of a list.

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

shuffleSeq :: MonadGen m => Seq a -> m (Seq a) Source #

Generates a random permutation of a sequence.

*This shrinks towards the order of the sequence being identical to the input*
*sequence.*

# Sampling Generators

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

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 () Source #

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 () Source #

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 () Source #

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

Use `printTree`

to generate a value from a random seed.

renderTree :: Show a => Size -> Seed -> Gen a -> String Source #

Render the shrink tree produced by a generator, for the given size and 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 -> TreeT (MaybeT m) a Source #

Runs a generator, producing its shrink tree.

evalGenT :: Monad m => Size -> Seed -> GenT m a -> TreeT m (Maybe a) Source #

Runs a generator, producing its shrink tree.

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

Map over a generator's shrink tree.

toTree :: forall m a. (MonadGen m, GenBase m ~ Identity) => m a -> m (Tree a) Source #

Observe a generator's shrink tree.

toTreeMaybeT :: MonadGen m => m a -> m (TreeT (MaybeT (GenBase m)) a) Source #

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

fromTree :: MonadGen m => Tree a -> m a Source #

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

fromTreeT :: MonadGen m => TreeT (GenBase m) a -> m a Source #

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

fromTreeMaybeT :: MonadGen m => TreeT (MaybeT (GenBase m)) a -> m a Source #

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

## Size

golden :: Size -> Size Source #

Scale a size using the golden ratio.

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

## Shrinking

atLeast :: Int -> [a] -> Bool Source #

Check that list contains at least a certain number of elements.

## Characters

isSurrogate :: Char -> Bool Source #

Check if a character is in the surrogate category.

isNoncharacter :: Char -> Bool Source #

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

## Subterms

#### Instances

Functor (Vec n) Source # | |

Foldable (Vec n) Source # | |

Defined in Hedgehog.Internal.Gen fold :: Monoid m => Vec n m -> m # foldMap :: Monoid m => (a -> m) -> Vec n a -> 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) Source # | |