Thanks to aavogt on the #haskell channel, I found the module Control.Spoon
, which provides the functions spoon and teaspoon which can be used to solve this problem. However, I don't know how safe it is to use this package (which uses unsafePerformIO internally
).
Anyway, using Control.Spoon
, prop
can be rewritten the following way:
prop x =
printTestCase ("Failed for value " ++ show pureFailure) $ isNothing excFailure
where
pureFailure = failure (fromMaybe True . teaspoon)
excFailure = failure id
failure g = fmap fst $ find (g . not . snd) $ map (\n -> (n, f x n == n)) [10..20]
Wrapping the find predicate with fromMaybe True . teaspoon
has the effect that find returns
the first element either satisfying the predicate or throwing an exception.
As teaspoon
can only be used to see that an exception occured, but not which, I use
excFailure
here so that QuickCheck still sees the exception. The downside is that the find
needs to be evaluated twice. teaspoon
only evaluates to WHNF, if you need a deep evaluation to trigger the exception, use spoon
instead.
teaspoon
catches only a few select exceptions, which is fine for me, because I only really care about undefined and inexhaustive pattern matches.