This QuickCheck generator
notEqual :: Gen (Int, Int)
notEqual = do
(a, b) <- arbitrary
if a /= b
then return (a, b)
else notEqual
Doesn't seem to terminate when passed to forAll
. I'm guessing the recursion is going into an infinite loop somehow, but why?
The suchThat
combinator that @Ashesh and @Carsten pointed out is definitely what I am looking for, to succinctly and idiomatically generate a non-equal pair.
An explanation for the infinite recursion (Thanks to @oisdk):
All QuckCheck runners (quickCheck
, forAll
etc.) pass a size parameter to test genarators. This has no defined semantics, but early tests use a small parameter, starting at 0*, and gradually growing. Generators use this to generate samples of different 'sizes,' whatever that may mean for a specific datatype.
arbitrary
for integral types (called recursively by arbitrary
for (Int, Int)
), uses this for the magnitude of the generated value - generate an integral between 0 and size
.
This means, unfortunately, that the first test attempted by quickCheck
, (or in my case forAll
,) uses the size 0, which can only generate (0, 0)
. This always fails the test of /=
, causing the action to recurse infinitely, looking for more.
* I'm assuming this, as the behaviour of the size parameter doesn't seem to be documented anywhere.