[Haskell-cafe] Co-arbitrary
Malcolm Wallace
Malcolm.Wallace at cs.york.ac.uk
Tue May 8 04:48:39 EDT 2007
Joel Reymont <joelr1 at gmail.com> writes:
> Would someone kindly explain why we need co-arbitrary in QuickCheck
> and how to define it?
Ever written a higher-order function and wanted to quickcheck it?
So where do you get your random functional arguments from?
Whereas the 'arbitrary' method allows you to write a generator for
random values of a constructed datatype, the 'coarbitrary' method allows
you to write a generator for random *functions* that take a
randomly-generated value as argument, and produce a randomly-generated
result that is nevertheless determined by / dependent on the argument.
> Detailed examples would be awesome!
There are lots of instances already defined in Test.QuickCheck that are
worth reading. In almost all cases they use the generator-combinator
'variant', which is like 'coarbitrary' but selects its result based on
an Int rather than a value of an arbitrary datatype. So in most cases,
implementing 'coarbitrary' amounts to converting the given argument to
an appropriate Int to pass to 'variant'.
instance Arbitrary Bool where
coarbitrary b = if b then variant 0 else variant 1
The result type of 'corarbitrary' (and 'variant') :: Gen b -> Gen b
means that, once some other part of the quickcheck apparatus has
determined what the result type of the generated function should be
(i.e. b), then given that we already have a random generator for one of
those result values, what we are doing is *modifying* that
result-generator to be dependent on the function's argument rather than
entirely arbitrary.
So in the Bool instance, 'coarbitrary' gives you a function-generator
that picks a 0-based result-generator in the False case, or a 1-based
result-generator in the True case.
To write your own 'coarbitrary', you are aiming to convert values of
your datatype into a disjoint partition of the set of all Ints. In
the end it is rather mechanical: e.g.
data Foo a = Foo String a
| Bar Bool
instance Arbitrary (Foo a) where
coarbitrary (Foo s a) = variant 0 . coarbitrary s . coarbitrary a
coarbitrary (Bar b) = variant 1 . coarbitrary b
Regards,
Malcolm
More information about the Haskell-Cafe
mailing list