Proposal: free shrinking with QuickCheck

Joseph Abrahamson me at jspha.com
Fri Nov 22 20:57:28 UTC 2013


I really like this idea, but I think I’d personally love to see some examples of it in practice. 75% of my Arbitrary instances are “traverse arbitrarily” and 95% of them keep Gen abstract, so I have a good feeling that it’d be possible to implement with relatively small amounts of user pain.

The thing I wonder about is how often `arbitrary` declarations provide enough information for efficient, meaningful `shrink` declarations. If the two differ it may be more necessary to break into `Gen` to provide the right kind of behavior—which would be increasingly complex.

I’d love to see some examples of complex generators from simple-check implemented in this style. As an ugly example I frequently run into in my own code, it’s often hard to write a good arbitrary instance for UTCTime—it’s very domain specific what defines a good arbitrary time. Would such kinds of complex generator code also lead to a nice shrink function? Or would it require something more complex?

-- 
Joseph Abrahamson
Sent with Airmail

On November 22, 2013 at 2:18:13 PM, Reid Draper (reiddraper at gmail.com) wrote:


On Nov 22, 2013, at 12:02 PM, Bryan O'Sullivan <bos at serpentine.com> wrote:


On Thu, Nov 21, 2013 at 4:27 PM, Reid Draper <reiddraper at gmail.com> wrote:
I originally sent this message to the QuickCheck mailing list,
but haven't heard anything in a while, and realized there are
only ten subscribers. Below is the original message, any feedback
appreciated.

I don't love this idea on first reading. The move to switch to generating a rose tree seems rather intrusive and like it could put a lot of complexity right in the paths of developers. That being said, I'd be interested in seeing the idea fleshed out to the point of determining whether my worry has any teeth - could the end-user writing of an Arbitrary instance remain unaffected in practice?

I'll take a stab at a minimal implementation. The goal would certainly be for users to be able to simply delete their `shrink` function. If they were previously using the default (shrink _ = []), they'd then get shrinking for free. For those looking for more motivation, take a look at how boilerplate shrink implementations end up being in practice. Further, care must be given to respect any implicit constraints during shrinking, that are respected during generation. For example, when generating with `choose 10 20`, you must never shrink to a value below 10. This would all be taken care of using the proposed method.

critbit: https://github.com/bos/critbit/blob/master/tests/Properties/Common.hs#L32-L33
a boolean logic solver: https://github.com/reiddraper/haskell-logic/blob/master/logic.hs#L89-L106
pandoc, which doesn't have shrinking, conceivably it'd be quite tedious: https://github.com/jgm/pandoc/blob/master/tests/Tests/Arbitrary.hs

_______________________________________________  
Libraries mailing list  
Libraries at haskell.org  
http://www.haskell.org/mailman/listinfo/libraries  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/libraries/attachments/20131122/365d3744/attachment-0001.html>


More information about the Libraries mailing list