QuickCheck: why isn't there a function to pass a test and what to use instead?

148 views Asked by At

Why isn't there a QuickCheck function similar to hedgehog's success? In particular I was wondering how one could translate a property like the following one:

prop_specialPair :: Property
prop_specialPair = property $ do
  (_, xs) <- forAll specialPair
  case xs of
    x:_ -> x /== 3
    _   -> success

In QuickCheck if I use =/= then I'm forced to return something of type Property, and there seem to be no constant function to return a passing property.

So I either have to resort to the Bool type:

prop_specialPair :: SpecialPair -> Bool
prop_specialPair SpecialPair { xs } =
  case xs of
    x:_ -> x == 3
    _   -> True

Or use a very awkward encoding for success, e.g.:

prop_specialPair :: SpecialPair -> Property
prop_specialPair SpecialPair { xs } =
  case xs of
    x:_ -> x =/= 3
    _   -> True === True

Are there better ways to express the property above in QuickCheck?

2

There are 2 answers

1
Fyodor Soikin On BEST ANSWER

You can use the property function from the Testable class, and various Testable instances to create a Property with whatever characteristics you need.

For example, property () always succeeds. For another example, property (b :: Bool) succeeds iff b == True.

So you could do this for example:

prop_specialPair :: SpecialPair -> Property
prop_specialPair SpecialPair { xs } =
  case xs of
    x:_ -> x =/= 3
    _   -> property ()

Or you can make it more explicit by using the Testable Result instance and the value succeeded :: Result:

prop_specialPair :: SpecialPair -> Property
prop_specialPair SpecialPair { xs } =
  case xs of
    x:_ -> x =/= 3
    _   -> property succeeded
0
sshine On

You could also use implication with (==>):

prop_specialPair :: Property
prop_specialPair =
  forAll specialPair $ \(_, xs) ->
    not (null xs) ==> take 1 xs =/= [3]