QuickCheck-2.7.3: Automatic testing of Haskell programs

Safe Haskell | Safe-Inferred
Language | Haskell98

Test.QuickCheck.Arbitrary

Contents

- Arbitrary and CoArbitrary classes
  - Helper functions for implementing arbitrary
  - Helper functions for implementing shrink
  - Helper functions for implementing coarbitrary
  - Generators which use arbitrary

Description

Type classes for random generation of values.

Synopsis

- class Arbitrary a where
  - arbitrary :: Gen a
  - shrink :: a -> [a]
- class CoArbitrary a where
  - coarbitrary :: a -> Gen b -> Gen b
- arbitrarySizedIntegral :: Integral a => Gen a
- arbitraryBoundedIntegral :: (Bounded a, Integral a) => Gen a
- arbitrarySizedBoundedIntegral :: (Bounded a, Integral a) => Gen a
- arbitrarySizedFractional :: Fractional a => Gen a
- arbitraryBoundedRandom :: (Bounded a, Random a) => Gen a
- arbitraryBoundedEnum :: (Bounded a, Enum a) => Gen a
- genericShrink :: (Generic a, Typeable a, RecursivelyShrink (Rep a), Subterms (Rep a)) => a -> [a]
- subterms :: (Generic a, Typeable a, Subterms (Rep a)) => a -> [a]
- recursivelyShrink :: (Generic a, RecursivelyShrink (Rep a)) => a -> [a]
- shrinkNothing :: a -> [a]
- shrinkList :: (a -> [a]) -> [a] -> [[a]]
- shrinkIntegral :: Integral a => a -> [a]
- shrinkRealFrac :: RealFrac a => a -> [a]
- shrinkRealFracToInteger :: RealFrac a => a -> [a]
- coarbitraryIntegral :: Integral a => a -> Gen b -> Gen b
- coarbitraryReal :: Real a => a -> Gen b -> Gen b
- coarbitraryShow :: Show a => a -> Gen b -> Gen b
- coarbitraryEnum :: Enum a => a -> Gen b -> Gen b
- (><) :: (Gen a -> Gen a) -> (Gen a -> Gen a) -> Gen a -> Gen a
- vector :: Arbitrary a => Int -> Gen [a]
- orderedList :: (Ord a, Arbitrary a) => Gen [a]
- infiniteList :: Arbitrary a => Gen [a]

# Arbitrary and CoArbitrary classes

class Arbitrary a where

Random generation and shrinking of values.

Minimal complete definition

Nothing

Methods

arbitrary :: Gen a

A generator for values of the given type.

shrink :: a -> [a]

Produces a (possibly) empty list of all the possible immediate shrinks of the given value. The default implementation returns the empty list, so will not try to shrink the value.

Most implementations of `shrink` should try at least three things:

1. Shrink a term to any of its immediate subterms.
2. Recursively apply `shrink` to all immediate subterms.
3. Type-specific shrinkings such as replacing a constructor by a simpler constructor.

For example, suppose we have the following implementation of binary trees:

    data Tree a = Nil | Branch a (Tree a) (Tree a)

We can then define `shrink` as follows:

    shrink Nil = []
    shrink (Branch x l r) =
      -- shrink Branch to Nil
      [Nil] ++
      -- shrink to subterms
      [l, r] ++
      -- recursively shrink subterms
      [Branch x' l' r' | (x', l', r') <- shrink (x, l, r)]

There are a couple of subtleties here:

- QuickCheck tries the shrinking candidates in the order they appear in the list, so we put more aggressive shrinking steps (such as replacing the whole tree by `Nil`) before smaller ones (such as recursively shrinking the subtrees).
- It is tempting to write the last line as `[Branch x' l' r' | x' <- shrink x, l' <- shrink l, r' <- shrink r]` but this is the wrong thing! It will force QuickCheck to shrink `x`, `l` and `r` in tandem, and shrinking will stop once one of the three is fully shrunk.

There is a fair bit of boilerplate in the code above. We can avoid it with the help of some generic functions; note that these only work on GHC 7.2 and above. The function `genericShrink` tries shrinking a term to all of its subterms and, failing that, recursively shrinks the subterms. Using it, we can define `shrink` as:

    shrink x = shrinkToNil x ++ genericShrink x
      where
        shrinkToNil Nil = []
        shrinkToNil (Branch _ l r) = [Nil]

`genericShrink` is a combination of `subterms`, which shrinks a term to any of its subterms, and `recursivelyShrink`, which shrinks all subterms of a term. These may be useful if you need a bit more control over shrinking than `genericShrink` gives you.

A final gotcha: we cannot define `shrink` as simply ``shrink` x = Nil:`genericShrink` x` as this shrinks `Nil` to `Nil`, and shrinking will go into an infinite loop.

If all this leaves you bewildered, you might try ``shrink` = `genericShrink`` to begin with, after deriving `Generic` and `Typeable` for your type. However, if your data type has any special invariants, you will need to check that `genericShrink` can't break those invariants.

Instances

Arbitrary Bool |
Arbitrary Char |
Arbitrary Double |
Arbitrary Float |
Arbitrary Int |
Arbitrary Int8 |
Arbitrary Int16 |
Arbitrary Int32 |
Arbitrary Int64 |
Arbitrary Integer |
Arbitrary Ordering |
Arbitrary Word |
Arbitrary Word8 |
Arbitrary Word16 |
Arbitrary Word32 |
Arbitrary Word64 |
Arbitrary () |
Arbitrary OrdC |
Arbitrary OrdB |
Arbitrary OrdA |
Arbitrary C |
Arbitrary B |
Arbitrary A |
Arbitrary a => Arbitrary [a] |
(Integral a, Arbitrary a) => Arbitrary (Ratio a) |
HasResolution a => Arbitrary (Fixed a) |
(RealFloat a, Arbitrary a) => Arbitrary (Complex a) |
Arbitrary a => Arbitrary (Maybe a) |
Arbitrary a => Arbitrary (Smart a) |
Arbitrary a => Arbitrary (Shrink2 a) |
Integral a => Arbitrary (Small a) |
(Integral a, Bounded a) => Arbitrary (Large a) |
(Num a, Ord a, Arbitrary a) => Arbitrary (NonNegative a) |
(Num a, Ord a, Arbitrary a) => Arbitrary (NonZero a) |
(Num a, Ord a, Arbitrary a) => Arbitrary (Positive a) |
Arbitrary a => Arbitrary (NonEmptyList a) |
(Ord a, Arbitrary a) => Arbitrary (OrderedList a) |
Arbitrary a => Arbitrary (Fixed a) |
Arbitrary a => Arbitrary (Blind a) |
(CoArbitrary a, Arbitrary b) => Arbitrary (a -> b) |
(Arbitrary a, Arbitrary b) => Arbitrary (Either a b) |
(Arbitrary a, Arbitrary b) => Arbitrary (a, b) |
(Arbitrary a, ShrinkState s a) => Arbitrary (Shrinking s a) |
(Function a, CoArbitrary a, Arbitrary b) => Arbitrary (Fun a b) |
(Function a, CoArbitrary a, Arbitrary b) => Arbitrary ((:->) a b) |
(Arbitrary a, Arbitrary b, Arbitrary c) => Arbitrary (a, b, c) |
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d) => Arbitrary (a, b, c, d) |
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e) => Arbitrary (a, b, c, d, e) |

class CoArbitrary a where

Used for random generation of functions.

Methods

coarbitrary :: a -> Gen b -> Gen b

Used to generate a function of type `a -> b`. The first argument is a value, the second a generator. You should use `variant` to perturb the random generator; the goal is that different values for the first argument will lead to different calls to `variant`. An example will help:

    instance CoArbitrary a => CoArbitrary [a] where
      coarbitrary []     = variant 0
      coarbitrary (x:xs) = variant 1 . coarbitrary (x,xs)

Instances

CoArbitrary Bool |
CoArbitrary Char |
CoArbitrary Double |
CoArbitrary Float |
CoArbitrary Int |
CoArbitrary Int8 |
CoArbitrary Int16 |
CoArbitrary Int32 |
CoArbitrary Int64 |
CoArbitrary Integer |
CoArbitrary Ordering |
CoArbitrary Word |
CoArbitrary Word8 |
CoArbitrary Word16 |
CoArbitrary Word32 |
CoArbitrary Word64 |
CoArbitrary () |
CoArbitrary OrdC |
CoArbitrary OrdB |
CoArbitrary OrdA |
CoArbitrary C |
CoArbitrary B |
CoArbitrary A |
CoArbitrary a => CoArbitrary [a] |
(Integral a, CoArbitrary a) => CoArbitrary (Ratio a) |
HasResolution a => CoArbitrary (Fixed a) |
(RealFloat a, CoArbitrary a) => CoArbitrary (Complex a) |
CoArbitrary a => CoArbitrary (Maybe a) |
(Arbitrary a, CoArbitrary b) => CoArbitrary (a -> b) |
(CoArbitrary a, CoArbitrary b) => CoArbitrary (Either a b) |
(CoArbitrary a, CoArbitrary b) => CoArbitrary (a, b) |
(CoArbitrary a, CoArbitrary b, CoArbitrary c) => CoArbitrary (a, b, c) |
(CoArbitrary a, CoArbitrary b, CoArbitrary c, CoArbitrary d) => CoArbitrary (a, b, c, d) |
(CoArbitrary a, CoArbitrary b, CoArbitrary c, CoArbitrary d, CoArbitrary e) => CoArbitrary (a, b, c, d, e) |

## Helper functions for implementing arbitrary

arbitrarySizedIntegral :: Integral a => Gen a

Generates an integral number. The number can be positive or negative and its maximum absolute value depends on the size parameter.

arbitraryBoundedIntegral :: (Bounded a, Integral a) => Gen a

Generates an integral number. The number is chosen uniformly from the entire range of the type. You may want to use `arbitrarySizedBoundedIntegral` instead.

arbitrarySizedBoundedIntegral :: (Bounded a, Integral a) => Gen a

Generates an integral number from a bounded domain. The number is chosen from the entire range of the type, but small numbers are generated more often than big numbers. Inspired by demands from Phil Wadler.

arbitrarySizedFractional :: Fractional a => Gen a

Generates a fractional number. The number can be positive or negative and its maximum absolute value depends on the size parameter.

arbitraryBoundedRandom :: (Bounded a, Random a) => Gen a

Generates an element of a bounded type. The element is chosen from the entire range of the type.

arbitraryBoundedEnum :: (Bounded a, Enum a) => Gen a

Generates an element of a bounded enumeration.

## Helper functions for implementing shrink

genericShrink :: (Generic a, Typeable a, RecursivelyShrink (Rep a), Subterms (Rep a)) => a -> [a]

Shrink a term to any of its immediate subterms, and also recursively shrink all subterms.

subterms :: (Generic a, Typeable a, Subterms (Rep a)) => a -> [a]

All immediate subterms of a term.

recursivelyShrink :: (Generic a, RecursivelyShrink (Rep a)) => a -> [a]

Recursively shrink all immediate subterms.

shrinkNothing :: a -> [a]

Returns no shrinking alternatives.

shrinkList :: (a -> [a]) -> [a] -> [[a]]

Shrink a list of values given a shrinking function for individual values.

shrinkIntegral :: Integral a => a -> [a]

Shrink an integral number.

shrinkRealFrac :: RealFrac a => a -> [a]

Shrink a fraction.

shrinkRealFracToInteger :: RealFrac a => a -> [a]

Shrink a fraction, but only shrink to integral values.

## Helper functions for implementing coarbitrary

coarbitraryIntegral :: Integral a => a -> Gen b -> Gen b

A `coarbitrary` implementation for integral numbers.

coarbitraryReal :: Real a => a -> Gen b -> Gen b

A `coarbitrary` implementation for real numbers.

coarbitraryShow :: Show a => a -> Gen b -> Gen b

`coarbitrary` helper for lazy people :-).

coarbitraryEnum :: Enum a => a -> Gen b -> Gen b

A `coarbitrary` implementation for enums.

(><) :: (Gen a -> Gen a) -> (Gen a -> Gen a) -> Gen a -> Gen a

Deprecated: Use ordinary function composition instead

Combine two generator perturbing functions, for example the results of calls to `variant` or `coarbitrary`.

## Generators which use arbitrary

vector :: Arbitrary a => Int -> Gen [a]

Generates a list of a given length.

orderedList :: (Ord a, Arbitrary a) => Gen [a]

Generates an ordered list of a given length.

infiniteList :: Arbitrary a => Gen [a]

Generate an infinite list.