module Lecture02A where import Prelude hiding (reverse,(++),take,drop) import Test.QuickCheck ----------------- -- Modelling with Recursive Datatypes: a childrens mobile ----------------- data Shape = Cat | Dog | Pig deriving (Show,Eq) data Mobile = Single Shape | Mobile :---: Mobile deriving Show instance Eq Mobile where (==) = meq example :: Mobile example = Single Pig :---: (Single Cat :---: Single Dog) example2 = (Single Dog :---: Single Cat) :---: Single Pig type Weight = Int weightShape :: Shape -> Weight weightShape Cat = 1 weightShape Dog = 1 weightShape Pig = 2 weight :: Mobile -> Weight weight (Single s) = weightShape s weight (m :---: n) = weight m + weight n balanced :: Mobile -> Bool balanced (Single _) = True balanced (m :---: n) = weight m == weight n && balanced m && balanced n meq :: Mobile -> Mobile -> Bool meq (Single s) (Single s') = s == s' meq (m1 :---: n1) (m2 :---: n2) = m1 `meq` m2 && n1 `meq` n2 || m1 `meq` n2 && n1 `meq` m2 meq _ _ = False -- --------------------------------------------- -- Lists revisited data List a = Empty | Add a (List a) deriving Show -- psudocode for built-in lists: -- data [a] = [] | a:[a] -- Haskell lists can be though of as a convenient shorthand -- for the above datatype. listB = Add True (Add False Empty) listI = Add 1 (Add 2 (Add 3 Empty) --------------------- -- List Examples -- --------------------- -- polymorphic types -- example functions from the Prelude reverse :: [a] -> [a] reverse [] = [] reverse (x:xs) = reverse xs ++ [x] prop_reverse :: [Int] -> Bool -- choose a type for testing. -- Otherwise quickCheck chooses [()] which is not great -- for testing reverse. prop_reverse xs = reverse (reverse xs) == xs (++) :: [a] -> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x:(xs ++ ys) prop_append :: [Int] -> [Int] -> Bool prop_append xs ys = length (xs ++ ys) == length xs + length ys prop_append2 :: [Int] -> [Int] -> Bool prop_append2 xs ys = reverse (xs ++ ys) == reverse ys ++ reverse xs drop,take :: Int -> [a] -> [a] take n [] = [] take n _ | n <= 0 = [] take n (x:xs) = x: take (n-1) xs drop n [] = [] drop n xs | n <= 0 = xs drop n (_:xs) = drop (n-1) xs prop_takedrop :: Int -> [Int] -> Bool prop_takedrop n xs = take n xs ++ drop n xs == xs {- reverse a list append two lists append a list of lists take the first n elements from a list drop the first n elements from a list "zip" two lists together -} -- constraints -- e.g. sorting