
On 25 July 2011 20:01, Mark Spezzano
Hi all,
I still don't understand exactly how the QuickCheck "sized" function is meant to work, and what it's useful for. Please explain!
The size parameter indicates how "large" a value can be generated (e.g. how big an Int can be, how long a list should be, etc.). As I understand it, by default the size is passed around by QuickCheck in how it uses the Gen Monad and used automatically, increasing as more and more tests are done. Sometimes you want to explicitly use this value to get an "upper bound" when defining your own Arbitrary instances (e.g. see the Int instance for Arbitrary). Other times, you may wish to explicitly _limit_ the size to a pre-defined value (to stop recursion or the like; I have a couple of instances which use something like: \ s -> liftM Foo $ resize (min 2 s) arbitrary). Either way, you define a function of type "foo :: Int -> Gen a" and then your arbitrary instance becomes "arbitrary = sized foo".
Also, I think that class CoArbitrary can help to generate random *functions *(as opposed to values; but tell me if I'm wrong) but I don't see how this could be useful.
Can't really help you there as I've never used it.
Also what does shrink do?
Oh no, QuickCheck has found an Arbitrary value that breaks your property! But it's absolutely _huge_: the output from show for it takes up an entire page, and it will take _forever_ to track down the specific little thing that caused the problem! But if you implemented the shrink method, QC will use it to find a minimal case: it shrinks the broken value, and then tests the property on every possible shrinked value, recursing until it finds one where every shrunken value satisfies the property (if there are any); at which case it will return that minimal broken case to you.
Example code of these would be tremendously helpful understanding these concepts.
Real World Haskell has a chapter on QC. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com