Search code examples
haskellquickcheck

Running QuickCheck against Simple Test w/ Function


Given the following:

test :: (Int -> Int) -> Int -> Bool
test _ _ = True

After compiling the source, I try to run quickCheck test:

> quickCheck test
<interactive>:27:1:
    No instance for (Show (Int -> Int))
      arising from a use of ‘quickCheck’
    In the expression: quickCheck test
    In an equation for ‘it’: it = quickCheck test

Looking at this Show instance for functions, it appears to me that no such instance exists.

How can I run quickCheck test, i.e. get around or address the missing Show instance for Int -> Int?


Solution

  • QuickCheck has a special module Test.QuickCheck.Function for generating "functions" that can be showed (and also "shrinked", which is how QuickCheck simplifies its counterexamples). You can convert them to ordinary functions using apply. For example if you have the file:

    import Test.QuickCheck
    import Test.QuickCheck.Function
    
    test :: Fun Int Int -> Int -> Bool
    test _ _ = True
    
    test2 :: Fun Int Int -> Int -> Bool
    test2 f x = apply f x == x
    

    Then in GHCi:

    *Main> quickCheck test
    +++ OK, passed 100 tests.
    *Main> quickCheck test2
    *** Failed! Falsifiable (after 2 tests and 3 shrinks): 
    {_->0}
    1
    

    It is actually possible to define a Show instance for functions themselves, and use that. But unless your input type is a finite type like Bool, you won't be able to print all information about the function this way. You can import a dummy instance that shows no useful information from Text.Show.Functions.

    However, the Test.QuickCheck.Function.Fun type used above looks like it's been designed to give the essential information much more succinctly, so I'd certainly use that myself if possible.