Question

I wrote an implementation for foldl and wanted to check if it worked, I tried some cases and it seems to be working well but I want to make sure.

I read about quickCheck and tried it, but I can't seem to make it work, this is the code

foldl'' :: (b -> a -> b) -> b -> [a] -> b

test :: Eq b => (b -> a -> b) -> b -> [a] -> Bool
test f e ls = foldl'' f e ls == foldl f e ls

when I run quickCheck test it throws the following error:

No instance for (Show (b0 -> a0 -> b0))
  arising from a use of `quickCheck'
Possible fix:
  add an instance declaration for (Show (b0 -> a0 -> b0))
In the expression: quickCheck prueba
In an equation for `it': it = quickCheck prueba
Was it helpful?

Solution

Your property requires three inputs: a function, an element and a list. The problem is that QuickCheck does not know how to deal with functions in general.

One of the things QuickCheck needs to work, is the ability to write failing test cases to the console. For this, it needs values it can turn into a String--anything in the Show class. Since functions are not in Show, it can't use them for inputs. That's where your error message comes from.

In general, using randomly generated functions for testing is going to be pretty tricky. I'd just write some concrete functions instead and let QuickCheck randomly generate the starting value and the list of elements.

OTHER TIPS

There is a way to avoid the Show constraint on inputs using the Blind modifier, which will let you use QuickCheck's machinery for generating random functions.

-- Using Int instead of a, b which would be defaulted to () in GHCi
prueba :: Blind (Int -> Int -> Int) -> Int -> [Int] -> Bool
prueba (Blind f) e ls = foldl'' f e ls == foldl f e ls

That said, this means the failure output is nearly useless for debugging, as it will just print (*) for the blind input. (For demonstration, I defined foldl'' = foldr . flip)

> quickCheck prueba 
*** Failed! Falsifiable (after 4 tests and 2 shrinks):    
(*)
0
[1,0]

From what I understand, there is machinery for creating random functions in QuickCheck (see Test.QuickCheck.Function), but I can't say that I known this stuff well enough to tell you how to use it.

That being said, testing your property likely makes more sense with functions you choose yourself, so you could write something like quickCheck $ prueba (+), which will work fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top