__module__ Spec __where__
__import__ Test.QuickCheck
__import__ Data.List((\\), sort)
-- Spec: use specification based development techniques
-- Spec.Test: formulate and test properties about the program
-- Spec.Prove: reason about correctness of functional programs
-- Spec.Trans: transform programs on the basis of reasoning
-- Below is an attempt at a QuickCheck test suite for |qsort :: Ord a => [a] -> [a]|.
qsort :: Ord a => [a] -> [a]
qsort = sort
prop_minimumBad xs = head (qsort xs) == minimum xs
prop_orderedBad xs = ordered (qsort xs)
__where__ ordered [] = True
ordered (x**:**y**:**xs) = x <= y && ordered (y**:**xs)
prop_permutationBad xs = permutation xs (qsort xs)
__where__ permutation xs ys = null (xs \\ ys) && null (ys \\ ys)
-- Find and correct at least one bug per property in the test suite.
{-
quickCheck (prop_minimumBad :: [Int] -> Bool)
*** Failed! Exception: 'Prelude.head: empty list' (after 1 test):
[]
-}
prop_minimum :: [Int] -> Property
prop_minimum xs = not (null xs) ==> head (qsort xs) == minimum xs
-- Write a |main| function which tests the three properties (for lists of integers) using QuickCheck.
prop_ordered :: [Int] -> Bool
prop_ordered xs = ordered (qsort xs)
__where__ ordered [] = True
ordered [x] = True
ordered (x**:**y**:**xs) = x <= y && ordered (y**:**xs)
prop_permutation :: [Int] -> Bool
prop_permutation xs = permutation xs (qsort xs)
__where__ permutation xs ys = null (xs \\ ys) && null (ys \\ xs)
main = __do__ quickCheck prop_minimum
quickCheck prop_ordered
quickCheck prop_permutation
{-
Write a sized generator (|sizedList :: Gen a -> Gen [a]|) for random
lists. Make sure the list length is random (but bounded by the
current size).
-}
sizedList :: Gen a -> Gen [a]
sizedList g = sized $ \n ->
__do__ size <- choose (0, n)
myVector size g
myVector :: Int -> Gen a -> Gen [a]
myVector n g = sequence (replicate n g)
----------------------------------------------------------------
-- End of exam question
-- --------------------------------------------------------------
testBad = __do__ quickCheck (prop_minimumBad :: [Int] -> Bool)
quickCheck (prop_orderedBad :: [Int] -> Bool)
quickCheck (prop_permutationBad :: [Int] -> Bool)
----------------
-- Sanity check
sizedList' :: Gen a -> Gen (Int, [a])
sizedList' g = sized $ \n ->
__do__ size <- choose (0, n)
fmap ((,) n) $ myVector size g