module Examples.QuickCheck where import Test.QuickCheck import Data.Char import Data.List rev :: [a] -> [a] rev (x:y:xs) = y:x:xs rev xs = xs propRevSmall :: Property propRevSmall = rev [1,2] === [2,1] propRevTwice :: [Int] -> Property propRevTwice xs = rev (rev xs) === xs propRevMedium :: Property propRevMedium = conjoin [rev [1,2,2] === [2,2,1], rev [1,2,3] === [3,2,1]] propRevTwo :: [Int] -> [Int] -> Property propRevTwo xs ys = rev (xs ++ ys) === rev ys ++ rev xs -- *Examples.QuickCheck> quickCheck propRevSmall -- +++ OK, passed 1 test. -- *Examples.QuickCheck> quickCheck propRevTwice -- +++ OK, passed 100 tests. -- *Examples.QuickCheck> quickCheck propRevMedium -- *** Failed! Falsified (after 1 test): -- [2,3,1] /= [3,2,1] -- *Examples.QuickCheck> quickCheck propRevTwo -- *** Failed! Falsified (after 5 tests and 8 shrinks): -- [0] -- [0,1] -- [0,1,0] /= [1,0,0] propLast :: [Int] -> Property propLast xs = last xs === head (reverse xs) propLastFixed :: NonEmptyList Int -> Property propLastFixed (NonEmpty xs) = last xs === head (reverse xs) propCycle :: NonEmptyList Int -> NonNegative Int -> Property propCycle (NonEmpty xs) (NonNegative n) = cycle xs !! n === xs !! (mod n (length xs)) propToUpperChanges :: Char -> Property propToUpperChanges c = toUpper c =/= c propToUpperChangesLetter :: Property propToUpperChangesLetter = forAll (elements ['a'..'z']) propToUpperChanges listHasZero :: [Int] -> Bool listHasZero xs = elem 0 xs -- *Examples.QuickCheck> quickCheck (listHasZero [1,0,2]) -- +++ OK, passed 1 test. -- *Examples.QuickCheck> quickCheck listHasZero -- *** Failed! Falsified (after 1 test): -- [] propSort :: NonEmptyList Int -> Property propSort (NonEmpty xs) = forAll (elements xs) (\x -> elem x (sort xs)) propRevTwo' :: [Int] -> [Int] -> Property propRevTwo' xs ys = let input = xs ++ ys in counterexample ("Input: " ++ show input) $ rev input === rev ys ++ rev xs someLetters :: Gen String someLetters = do c <- elements "xyzw" n <- choose (1,10) return (replicate n c) data Switch = On | Off deriving (Show, Eq) toggle :: Switch -> Switch toggle On = Off toggle Off = On propToggleTwice :: Switch -> Property propToggleTwice s = s === toggle (toggle s) instance Arbitrary Switch where arbitrary = elements [On,Off]