Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module defines the Produce
typeclass, used for generating random
values for testing in StrictCheck.
Produce
is a strict generalization of Test.QuickCheck's Arbitrary
typeclass. Paired with Consume
(a generalization of CoArbitrary
) it can
be used to create random non-strict functions, whose strictness behavior is
dependent on the values given to them.
- class Produce b where
- recur :: (Produce a, ?inputs :: Inputs) => Gen a
- build :: (?inputs :: Inputs) => ((?inputs :: Inputs) => Gen a) -> Gen a
- returning :: (Consume a, ?inputs :: Inputs) => ((?inputs :: Inputs) => Gen b) -> Gen (a -> b)
- variadic :: forall args result. (All Consume args, Curry args, ?inputs :: Inputs) => ((?inputs :: Inputs) => Gen result) -> Gen (args ⋯-> result)
- newtype Lazy a = Lazy {
- runLazy :: a
- freely :: ((?inputs :: Inputs) => Gen a) -> Gen a
- data Input
- data Inputs
- draws :: [Input] -> Gen (Variant, [Input])
Documentation
class Produce b where Source #
Produce an arbitrary value of type b
, such that destructing that value
incrementally evaluates some input to a function.
Writing instances of Produce
is very similar to writing instances of
QuickCheck's Arbitrary
. The distinction: when making a recursive call to
produce a subfield of a structure, always use build
or recur
, and
never a direct call to produce
itself. This ensures that the input can
potentially be demanded at any step of evaluation of the produced value.
If, in the course of generating a value of type b
, you need to generate a
random value of some other type, which is not going to be a subpart of the
resultant b
(e.g. a length or depth), use a direct call to arbitrary
or
some other generator which does not consume input.
An example instance of Produce
:
data D a = X a | Y [Int] instance Produce a => Produce (D a) where produce = oneof [ fmap X recur , fmap Y recur ]
Produce Bool Source # | |
Produce Char Source # | |
Produce Double Source # | |
Produce Float Source # | |
Produce Int Source # | |
Produce Integer Source # | |
Produce Ordering Source # | |
Produce Rational Source # | |
Produce Word Source # | |
Produce () Source # | |
Produce Omega Source # | |
Produce KMap Source # | A dummy produce instance for the solution table. |
Produce Key Source # | A dummy produce instance for the index into the solution table. |
Produce a => Produce [a] Source # | |
Produce a => Produce (Maybe a) Source # | |
(Arbitrary a, RealFloat a) => Produce (Complex a) Source # | |
(Consume a, Produce b) => Produce (a -> b) Source # | |
(Produce a, Produce b) => Produce (Either a b) Source # | |
Tools for writing Produce
instances
recur :: (Produce a, ?inputs :: Inputs) => Gen a Source #
Destruct some inputs to generate an output. This function handles the interleaving of input destruction with output construction. When producing a data type, it should be called to produce each subfield -- *not* produce itself.
build :: (?inputs :: Inputs) => ((?inputs :: Inputs) => Gen a) -> Gen a Source #
Given an input-consuming producer, wrap it in an outer layer of input consumption, so that this consumption can be interleaved when the producer is called recursively to generate a subfield of a larger produced datatype.
Producing non-strict functions
returning :: (Consume a, ?inputs :: Inputs) => ((?inputs :: Inputs) => Gen b) -> Gen (a -> b) Source #
Create an input-consuming producer of input-consuming functions, given an input-consuming producer for results of that function.
variadic :: forall args result. (All Consume args, Curry args, ?inputs :: Inputs) => ((?inputs :: Inputs) => Gen result) -> Gen (args ⋯-> result) Source #
Create an input-consuming producer of input-consuming functions, of any arity. This will usually be used in conjuntion with type application, to specify the type(s) of the argument(s) to the function.
Integration with Test.QuickCheck's Arbitrary
We hook into QuickCheck's existing Arbitrary infrastructure by using a newtype to differentiate our special way of generating things.
freely :: ((?inputs :: Inputs) => Gen a) -> Gen a Source #
Actually produce an output, given an input-consuming producer. If a function is to be produced, it will be almost-certainly non-strict.
Abstract types representing input to a function
A tree representing all possible destruction sequences for a value Unfolding the contained lists forces a particular random control path for destructing the datatype.
A list of inputs given to a function, in abstract form. This lazy structure is evaluated piecewise during the course of producing a function, thus triggering the partial evaluation of the original input to the function.
The traversal distribution for processing Input
s
draws :: [Input] -> Gen (Variant, [Input]) Source #
Destruct a random subpart of the given Input
s, returning the Variant
corresponding to the combined information harvested during this process, and
the remaining "leaves" of the inputs yet to be destructed
To maximize the likelihood that different random consumption paths through
the same value will diverge (desirable when generating functions with
interesting strictness), draws
destructs the forest of Input
s as a
depth-first random traversal with a budget sampled from a geometric
distribution with expectation 1.