You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.9 KiB
109 lines
3.9 KiB
7 years ago
|
module PropTest where
|
||
|
|
||
|
import Test.QuickCheck
|
||
|
import Test.QuickCheck.Modifiers (NonZero)
|
||
|
import Test.QuickCheck.Function
|
||
|
import Data.List (sort)
|
||
|
|
||
|
-- Note:
|
||
|
-- quickCheck takes a type of the Testable typeclass
|
||
|
-- Arbitrary a => a -> Bool is an instance of this, since
|
||
|
-- Bool is also Testable.
|
||
|
|
||
|
-- 1
|
||
|
half :: Fractional a => a -> a
|
||
|
half = (/2)
|
||
|
halfIdentity :: Fractional a => a -> a
|
||
|
halfIdentity = (*2) . half
|
||
|
|
||
|
prop_half :: (Eq a, Fractional a) => a -> Bool
|
||
|
prop_half = \x -> halfIdentity x == x
|
||
|
|
||
|
-- 2
|
||
|
listOrdered :: (Ord a) => [a] -> Bool
|
||
|
listOrdered xs =
|
||
|
snd $ foldr go (Nothing, True) xs
|
||
|
where go _ status@(_,False) = status
|
||
|
go y (Nothing, t) = (Just y, t)
|
||
|
go y (Just x, _) = (Just y, x >= y)
|
||
|
prop_sort :: Ord a => [a] -> Bool
|
||
|
prop_sort = listOrdered . sort
|
||
|
|
||
|
-- 3
|
||
|
plusAssociative :: (Num a, Eq a) => a -> a -> a -> Bool
|
||
|
plusAssociative x y z = x + (y + z) == (x + y) + z
|
||
|
plusCommutative :: (Num a, Eq a) => a -> a -> Bool
|
||
|
plusCommutative x y = x + y == y + x
|
||
|
|
||
|
-- 4
|
||
|
multAssociative :: (Num a, Eq a) => a -> a -> a -> Bool
|
||
|
multAssociative x y z = x * (y * z) == (x * y) * z
|
||
|
multCommutative :: (Num a, Eq a) => a -> a -> Bool
|
||
|
multCommutative x y = x * y == y * x
|
||
|
|
||
|
-- 5
|
||
|
prop_quotRem :: (Eq a, Integral a) => a -> a -> Bool
|
||
|
prop_quotRem _ 0 = True -- exclude 0 from the test
|
||
|
prop_quotRem x y = (quot x y)*y + (rem x y) == x
|
||
|
prop_divMod :: (Eq a, Integral a) => a -> a -> Bool
|
||
|
prop_divMod _ 0 = True -- exclude 0 from the test
|
||
|
prop_divMod x y = (div x y)*y + (mod x y) == x
|
||
|
-- other solution would be the create a generator for Int or Integers or ...
|
||
|
-- which excludes 0
|
||
|
-- OR use the modifiers from quickcheck
|
||
|
prop_quotRem' :: (Eq a, Integral a) => NonZero a -> NonZero a -> Bool
|
||
|
prop_quotRem' (NonZero x) (NonZero y) = (quot x y)*y + (rem x y) == x
|
||
|
prop_divMod' :: (Eq a, Integral a) => NonZero a -> NonZero a -> Bool
|
||
|
prop_divMod' (NonZero x) (NonZero y) = (div x y)*y + (mod x y) == x
|
||
|
|
||
|
-- 6 These will fail
|
||
|
prop_eAss :: (Eq a, Num a, Integral a) => a -> a -> a -> Bool
|
||
|
prop_eAss x y z = x ^ (y ^ z) == (x ^ y) ^ z
|
||
|
prop_eCom :: (Eq a, Num a, Integral a) => a -> a -> Bool
|
||
|
prop_eCom x y = x ^ y == y ^ x
|
||
|
|
||
|
-- 7
|
||
|
prop_reverse :: Eq a => [a] -> Bool
|
||
|
prop_reverse xs = (reverse . reverse) xs == id xs
|
||
|
|
||
|
-- 8
|
||
|
prop_apply :: Eq b => (Fun a b) -> a -> Bool
|
||
|
prop_apply (Fun _ f) a = (f $ a) == f a
|
||
|
prop_compose :: Eq c => (Fun b c) -> (Fun a b) -> a -> Bool
|
||
|
prop_compose (Fun _ f) (Fun _ g) a = (f . g) a == f (g a)
|
||
|
|
||
|
-- 9
|
||
|
prop_append :: Eq a => [a] -> [a] -> Bool
|
||
|
prop_append xs ys = foldr (:) xs ys == (++) xs ys
|
||
|
prop_concat :: Eq a => [[a]] -> Bool
|
||
|
prop_concat xs = foldr (++) [] xs == concat xs
|
||
|
|
||
|
-- 10
|
||
|
prop_length :: Int -> [a] -> Bool
|
||
|
prop_length n xs = length (take n xs) == n
|
||
|
|
||
|
-- 11
|
||
|
prop_readshow :: (Read a, Show a, Eq a) => a -> Bool
|
||
|
prop_readshow x = (read (show x)) == x
|
||
|
|
||
|
main :: IO ()
|
||
|
main = do
|
||
|
quickCheck (prop_half :: Double -> Bool) -- Float can also be checked
|
||
|
quickCheck (prop_sort :: [Int] -> Bool) -- Lots of other options available
|
||
|
quickCheck (plusAssociative :: Int -> Int -> Int -> Bool)
|
||
|
quickCheck (plusCommutative :: Integer -> Integer -> Bool)
|
||
|
quickCheck (multAssociative :: Int -> Int -> Int -> Bool)
|
||
|
quickCheck (multCommutative :: Integer -> Integer -> Bool)
|
||
|
quickCheck (prop_quotRem :: Integer -> Integer -> Bool)
|
||
|
quickCheck (prop_divMod :: Integer -> Integer -> Bool)
|
||
|
quickCheck (prop_quotRem' :: NonZero Integer -> NonZero Integer -> Bool)
|
||
|
quickCheck (prop_divMod' :: NonZero Integer -> NonZero Integer -> Bool)
|
||
|
quickCheck (prop_eAss :: Integer -> Integer -> Integer -> Bool) -- fails
|
||
|
quickCheck (prop_eCom :: Integer -> Integer -> Bool) -- fails
|
||
|
quickCheck (prop_reverse :: [Char] -> Bool)
|
||
|
quickCheck (prop_apply :: (Fun Integer Integer) -> Integer -> Bool)
|
||
|
quickCheck (prop_compose :: (Fun Int Int) -> (Fun Int Int) -> Int -> Bool)
|
||
|
quickCheck (prop_append :: [Char] -> [Char] -> Bool)
|
||
|
quickCheck (prop_concat :: [[Char]] -> Bool)
|
||
|
quickCheck (prop_length :: Int -> [String] -> Bool)
|
||
|
quickCheck (prop_readshow :: Int -> Bool)
|