开发者

Avoiding duplicated QuickCheck properties

开发者 https://www.devze.com 2023-04-10 17:44 出处:网络
I\'m starting to learn Haskell by doing the 99 Haskell problems.http://www.haskell.org/haskellwiki/H-99:_Ninety-Nine_Haskell_ProblemsI\'d like to write tests for each program/function using quickcheck

I'm starting to learn Haskell by doing the 99 Haskell problems. http://www.haskell.org/haskellwiki/H-99:_Ninety-Nine_Haskell_Problems I'd like to write tests for each program/function using quickcheck.

I have the following code:

import Test.QuickCheck
import Text.Printf

main  = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests

-- 1
myLast  lst = last lst
prop_1a xs x = myLast  (xs ++ [x]) == (x::String)

myLast' = head . reverse
prop_1b xs x = myLast' (xs ++开发者_如何学C [x]) == (x::String)

tests  = [("1a",                 quickCheck prop_1a)
         ,("1b",                 quickCheck prop_1b)
         ]

I might write myLast'', myLast''', etc. Is there a way I can test all those methods without having to duplicate code and quickcheck properties?

Related question: Right now, I'm telling quickcheck to use Strings. Is there a way to randomly use different types to test against?


Just take the function to test as another argument:

prop_1 last xs x = last (xs ++ [x]) == (x :: Int)

tests = zipWith mkTest ['a'..] [myLast, myLast']
  where mkTest letter func = ('1':[letter], quickCheck $ prop_1 func)


Is there a way I can test all those methods without having to duplicate code and quickcheck properties?

Why not write the prop so that it takes a list of functions, and then does the check on each of them? Then you'd run it as quickCheck (myProp [myLast, myLast', myLast'']).

edit: I was afraid you might ask that :P To do it as I said above, myProp should take a list of functions, all of which have the same type as last, and return a boolean:

myProp :: [([a] -> a)] -> Bool

But now that I look at it, it might be better (and more analogous to your original approach) to have it also take a list and an item, so I think I'll do that instead:

myProp :: [([a] -> a)] -> [a] -> a -> Bool

If the list is empty then we return true:

myProp [] _ _ = True

If not, then we check whether the property holds for the first function in the list, then recursively check the rest of the list:

myProp [f:fs] xs x = f (xs ++ [x]) == x && myProp fs xs x

(I'm not sure why you wrote x::String in your implementation. I don't think you should need it -- last works on lists of anything, not just lists of Strings. But I haven't actually tested this out so I assume you had a good reason.)

Anyway, I think that should work but I haven't actually tried it. Please feel free to edit and fix any dumb syntax errors I may have made or whatever.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号