
Would someone kindly explain why we need co-arbitrary in QuickCheck and how to define it? Detailed examples would be awesome! I would be willing to paste an in-depth explanation on my wall and keep it forever. Thanks in advance, Joel -- http://wagerlabs.com/

joelr1:
Would someone kindly explain why we need co-arbitrary in QuickCheck and how to define it?
Generating random function generators. A nice explanation was given recently on the programming subreddit: "The CoArbitrary class continues to confuse me" http://programming.reddit.com/info/1mcu8/comments/c1md04
Detailed examples would be awesome!
I would be willing to paste an in-depth explanation on my wall and keep it forever.
-- Don

Joel Reymont
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

Hi
Would someone kindly explain why we need co-arbitrary in QuickCheck and how to define it?
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
The Derive tool now implements coarbitrary for the instances it generates - following the scheme outlined in this email. http://www-users.cs.york.ac.uk/~ndm/derive/ Thanks Neil

On May 8, 2007, at 9:33 , Joel Reymont wrote:
Would someone kindly explain why we need co-arbitrary in QuickCheck and how to define it?
Detailed examples would be awesome!
I would be willing to paste an in-depth explanation on my wall and keep it forever.
Thanks in advance, Joel
Maybe this can help: http://www.cs.chalmers.se/~rjmh/QuickCheck/ manual_body.html#18 /Björn
participants (5)
-
Bjorn Bringert
-
dons@cse.unsw.edu.au
-
Joel Reymont
-
Malcolm Wallace
-
Neil Mitchell