import Prelude hiding (Either(..)) import Test.QuickCheck import Data.List -- Insert an element into a sorted list: --ins :: Int -> [Int] -> [Int] ins x [] = [x] ins x (y:ys) = if x < y then x : y : ys else y : ins x ys -- Insertion sort: --isort :: [Int] -> [Int] isort [] = [] isort (x:xs) = ins x (isort xs) prop_same_length :: [Int] -> Bool prop_same_length xs = length xs == length (isort xs) -- ... -- Tests again an existing sort function (Data.List: sort) prop_reference :: [Int] -> Bool prop_reference xs = isort xs == Data.List.sort xs ---------------------------------------------------------------------------- -- Classify test cases: -- Show the smaller tests: prop_reference_small :: [Int] -> Property prop_reference_small xs = classify (length xs < 5) "small" $ isort xs == Data.List.sort xs -- Show the smaller tests: prop_reference_small_big :: [Int] -> Property prop_reference_small_big xs = classify (length xs < 5) "small" $ classify (length xs > 20) "big" $ classify (length xs > 50) "bigger" $ isort xs == Data.List.sort xs -- Show the smaller tests: prop_reference_collect :: [Int] -> Property prop_reference_collect xs = collect (length xs) $ isort xs == Data.List.sort xs ---------------------------------------------------------------------------- -- Generate test values: -- Data type for my own (small) numbers: data Digit = Digit Int deriving (Eq, Ord) instance Show Digit where show (Digit n) = show n -- Tests again an existing sort function (Data.List: sort) prop_reference_digit :: [Digit] -> Bool prop_reference_digit xs = isort xs == Data.List.sort xs -- Type class of QuickCheck for generating test values: {- class Arbitrary a where arbitrary :: Gen a -- random generator as a monad ("do" notation) -} instance Arbitrary Digit where arbitrary = do --d <- elements [0 .. 9] d <- choose (0,9) return (Digit d) data Either a b = Left a | Right b instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b) where arbitrary = do x <- arbitrary y <- arbitrary oneof [return (Left x), return (Right y)] -- our own polymorphic lists: data List a = Empty | Cons a (List a) instance Arbitrary a => Arbitrary (List a) where arbitrary = sized $ \n -> do k <- choose (0,n) makeArbitraries k -- Create an arbitrary list of the given length: makeArbitraries :: Arbitrary a => Int -> Gen (List a) makeArbitraries n | n <= 0 = return Empty | otherwise = do x <- arbitrary xs <- makeArbitraries (n - 1) return (Cons x xs) -- predefined as -- vector :: Arbitrary a => Int -> Gen [a]