{-# LANGUAGE InstanceSigs #-} -- In order to use quickcheck library, -- you will need to do: cabal install QuickCheck --lib -- in the command line. import Test.QuickCheck distance :: Int -> Int -> Int distance x y = abs (y-x) -- The distance between any number and itself is always 0 prop_dist_self :: Int -> Bool prop_dist_self x = distance x x == 0 -- The distance between x and y is equal to the distance between y and x prop_dist_symmetric :: Int -> Int -> Bool prop_dist_symmetric x y = distance x y == distance y x -- quickCheck :: Testable prop => prop -> IO () -- verboseCheck :: Testable prop => prop -> IO () -- withMaxSuccess :: Testable prop => Int -> prop -> Property -- QuickCheck's Testable class. -- what if we forget abs when defining distance. qsort :: Ord a => [a] -> [a] qsort [] = [] qsort (x:xs) = qsort lhs ++ [x] ++ qsort rhs where lhs = filter (< x) xs rhs = filter (>= x) xs prop_idempotent :: [Int] -> Bool prop_idempotent xs = qsort (qsort xs) == qsort xs prop_idempotent1 :: [Float] -> Bool prop_idempotent1 xs = qsort (qsort xs) == qsort xs prop_first_elem :: [Int] -> Bool prop_first_elem xs = if null xs then True else let ys = qsort xs in head ys == minimum xs prop_first_elem' :: [Int] -> Property prop_first_elem' xs = (not (null xs)) ==> head (qsort xs) == minimum xs sorted :: Ord a => [a] -> Bool -- sorted ls = foldr (\ x r -> ) True ls -- sorted :: Ord a => [a] -> Bool sorted [] = True -- sorted [x] = True sorted (x:xs) = x <= head xs && sorted xs prop_sorted :: [Int] -> Bool prop_sorted xs = sorted $ qsort xs prop_quick_sort :: [Int] -> Property prop_quick_sort xs = undefined -- How to find properties to test? append :: [a] -> [a] -> [a] append [] xs = xs append (y:ys) xs = y : append ys xs -- 1. Algebraic laws. prop_app_unit :: [Int] -> Bool prop_app_unit xs = append xs [] == xs prop_app_unit' :: [Int] -> Bool prop_app_unit' xs = xs == append [] xs prop_app_assoc :: [Int] -> [Int] -> [Int] -> Bool prop_app_assoc xs ys zs = append (append xs ys) zs == append xs (append ys zs) -- 2. Equivalent of implementations. prop_qsort_sort :: [Int] -> Bool prop_qsort_sort xs = undefined -- qsort xs == bubbleSort xs -- Some other way to build testable properties. -- Let's test the 'replicate' function. prop_replicate :: Int -> Int -> Int -> Bool prop_replicate n x i = replicate n x !! i == x -- A better property using '==>' prop_replicate' :: Int -> Int -> Int -> Property prop_replicate' n x i = (i < n && 0 <= i) ==> replicate n x !! i == x prop_replicate2 :: Char -> Property prop_replicate2 x = forAll (choose (1, 1000)) $ \ n -> forAll (choose (0, n-1)) (\ i -> replicate n x !! i == x) -- Quickcheck's Arbitrary class and the 'generate' function. -- Some useful combinators for generators -- generate $ choose (0,1) -- generate $ elements ['a','e','i','o','u'] -- generate $ (vector 100 :: Gen [Int]) -- generate $ frequency [(99, elements [True]), (1, elements [False])] -- generate $ shuffle [0 .. 10] data Color = Red | Blue | Green deriving (Show) instance Arbitrary Color where arbitrary :: Gen Color arbitrary = elements [Red, Blue, Green] data List a = Nil | Cons a (List a) deriving (Show) instance (Arbitrary a) => Arbitrary (List a) where arbitrary :: Gen (List a) arbitrary = frequency [(1, elements [Nil]) , (2, do{x <- arbitrary; xs <- arbitrary; return (Cons x xs)})] data BinaryTree a = Empty | Node a (BinaryTree a) (BinaryTree a) deriving (Show) instance (Arbitrary a) => Arbitrary (BinaryTree a) where arbitrary :: Gen (BinaryTree a) arbitrary = frequency [(4, elements [Empty]) , (2, do{x <- arbitrary; l <- arbitrary; r <- arbitrary; return (Node x l r)})]