module Lecture3A where import Test.QuickCheck -- Lecture 3A. -- 0. Beautification of Bool -- 1. recursion in two parameters -- 2. Parameterised datatypes -- 3. Lists of lists -- 4. Type Classes -- 0. Boolean errors -- say a number is small if it is bigger than -10 -- and smaller than 10 isSmall :: Integer -> Bool isSmall x = x >(-10) && x < 10 -- | (x >(-10) && x < 10) == True = True -- | (x >(-10) && x < 10) == False = False evil x = abs x == 666 notEvil x = not(evil x) -- Functions with guards should not usually return -- Bool -- Don't test for equality with literals -- True and False -- 1. Recursion in two parameters zip' :: [a] -> [b] -> [(a, b)] -- zip' [] _ = [] -- zip' _ [] = [] zip' (a:as) (b:bs) = (a,b) : zip' as bs zip' _ _ = [] -- zip -- Define with list comprehensions? zip'' as bs = [(a,b) | a <- as, b <- bs] prop_zip :: [Int] -> [Int] -> Bool prop_zip xs ys = zip xs ys == zip'' xs ys -- zip -- index (!!) _ !!! n | n < 0 = error "negative index" [] !!! _ = error "index too big" (x:xs) !!! 0 = x (x:xs) !!! n = xs !!! (n-1) -- (!!) -- Define !! using list comprehension? index n xs = head [ v |(i,v) <- zip [0..] xs, i == n] -- testing !! ------------------- -- 3. Parameterised datatypes -- Haskell functions can be partial -- (not defined for some arguments) -- e.g. head [], [1,2]!!9, 1 `div` 0, last [1..] -- Example: Maybe -- data Maybe a = Just a | Nothing safeDiv :: Int -> Int -> Maybe Int safeDiv n 0 = Nothing safeDiv n m = Just (n `div` m) -- Examples of standard functions in Data.Maybe -- import Data.Maybe fromJust :: Maybe a -> a fromJust (Just v) = v fromJust Nothing = error "..." isJust :: Maybe a -> Bool isJust (Just _) = True isJust _ = False catMaybes :: [Maybe a] -> [a] catMaybes ms = -- [fromJust m | m <- ms, isJust m] [v | Just v <- ms] ------------------------------------------------ -- 4. Working with List of lists -- and -- 5. Intro to Type class instances -- special cases [[Char]] -- concat --- Example: representing naughts-and-crosses -- Tic-tac-toe, tre-i-rad -- data Grid = Grid [[Mark]] -- deriving Show instance Show Grid where show (Grid mss) = unlines [ showRow ms| ms <- mss] where showRow ms = unwords [show m| m <- ms ] data Mark = Naught | Cross | Blank -- deriving Show instance Show Mark where show Naught = "O" show Cross = "X" show Blank = " " exampleGrid :: Grid exampleGrid = Grid [[Naught,Blank,Naught], [Blank,Naught,Cross], [Cross,Cross,Naught]] prop_Grid :: Grid -> Bool -- legal grids have n rows, each with n elements,doe some n > 0. prop_Grid = error "unfinished exercise" -- diagonals -- Exercise win :: Grid -> Bool -- Friday & Monday lecture