I have this test I want to make:
prop_inverse_stringsToInts st = isDigitList st ==> st == map show (stringsToInts st)
Which is testing a function that converts a list of Strings to a list of Integers, but of course the strings need to be digits so I created a pre-condition that checks that using the isDigitList function I made, but the condition is too specific and quickCheck gives up : "*** Gave up! Passed only 43 tests; 1000 discarded tests." So I wanted to create an Arbitrary instance for my case, but the thing is I am inexperienced with working with Arbitrary, so I don't really know how to do this and every time I shuffle code I get a new error. All I want is an Arbitrary that only returns the Foo [String] if it passes the isDigitList (which receives a [String] and returns a Bool). So far I have something like this :
Foo a = Foo [String] deriving (Show,Eq)
instance (Arbitrary a) => Arbitrary (Foo a ) where
arbitrary = do
st <- (arbitrary :: Gen [String])
if isDigitList st
then do return (Foo st)
else do return (Foo []) -- This is probably a bad idea
I altered my property to :
prop_inverse_stringsToInts :: Foo a -> Bool
prop_inverse_stringsToInts (Foo st) = st == map show (stringsToInts st)
But now I am getting the error "* Ambiguous type variable a0' arising from a use of `quickCheck'" even though I am running quickCheck like this : > quickCheck (prop_inverse_stringsToInts :: Foo a -> Bool)
Can someone help please? Thank you in advance!
Foo
to have a type argument. Try just making it `newtype Foo = Foo [String] deriving (Show, Eq). That should get rid of your "Ambiguous type variable" error. – DDuba
parameter, what's its purpose? Also, your instance looks morally wrong: you should not simply discard bad lists, silencing the QuickCheck "gave up" message, you should generate good lists instead. – chiprop_inverse_stringsToInts ints = ints == stringsToInts (map show ints)
. That is, instead of trying to generateString
s that can be converted toInt
s and back, generateInt
s, so that you know they can be converted. – DDuba
parameter for the returns to work but I was wrong... And @chi what would you do to generate a good list instead? Thanks again!!! – XplosiveFistchoose ('0','9')
can generate one of the intended digits. Exploiting that you should be able to generate a list of surely-good digits. Right now I guess that 90%+ of theFoo
you generate are empty lists, making testing 10x slower or more. In your own test only 43 cases (of 1000) were good, andFoo
simply makes the other 957 "good" mapping them to the empty list. Alternatively, generate the integers instead, as done by DDub. – chi