-- Examples from the first lecture (AFP_01) module Types where -- I. Algebraic Datatypes data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Eq,Show,Ord,Enum,Bounded) next :: Day -> Day next Mon = Tue next Tue = Wed next Wed = Thu next Thu = Fri next Fri = Sat next Sat = Sun next Sun = Mon -- shorter version, using Haskell Prelude functions (AFP_02) next' :: Day -> Day next' x = toEnum ((fromEnum x) + 1 `mod` ((fromEnum Sun) + 1)) -- records data BI = BI { b :: Bool, i ::Int } deriving (Eq, Show) foo :: BI -> Int foo bi = if b bi then i bi else 0 -- Complex Numbers data Complex1 = Comp1 Float Float deriving (Eq,Show) -- build a complex number mkComp1 :: Float -> Float -> Complex1 mkComp1 r i = Comp1 r i -- extract real and imaginary components realPart1 :: Complex1 -> Float realPart1 (Comp1 r _) = r imagPart1 :: Complex1 -> Float imagPart1 (Comp1 _ i) = i data Complex2 a = Comp2 a a deriving (Eq,Show) -- build a complex number mkComp2 :: a -> a -> Complex2 a mkComp2 r i = Comp2 r i -- extract real and imaginary components realPart2 :: Complex2 a -> a realPart2 (Comp2 r _) = r imagPart2 :: Complex2 a -> a imagPart2 (Comp2 _ i) = i data (Num a) => Complex3 a = a :+ a deriving (Eq,Show) -- build a complex number mkComp3 :: (Num a) => a -> a -> Complex3 a mkComp3 r i = r :+ i -- extract real and imaginary components realPart3 :: (Num a) => Complex3 a -> a realPart3 (r :+ _) = r imagPart3 :: (Num a) => Complex3 a -> a imagPart3 (_ :+ i) = i -- Using records data Complex4 a = Comp4 { real :: a , imag :: a } deriving (Eq,Show) -- build a complex number mkComp4 :: a -> a -> Complex4 a mkComp4 r i = Comp4 { real = r, imag = i } -- extract real and imaginary components realPart4 :: Complex4 a -> a realPart4 x = real x imagPart4 :: Complex4 a -> a imagPart4 x = imag x -- compute a list of squares sqs1 :: [Int] -> [Int] sqs1 [] = [] sqs1 (x:xs) = x*x : sqs1 xs -- uses explicit case construct sqs2 :: [Int] -> [Int] sqs2 xs' = case xs' of [] -> [] (x:xs) -> x*x : sqs2 xs -- explicit bindings instead of pattern-matching sqs3 :: [Int] -> [Int] sqs3 xs' = if null xs' then [] else let x = head xs' -- note the layout rule: xs = tail xs' -- indented as much as above line in x*x : sqs3 xs -- using list comprehensions sqs_even :: [Int] -> [Int] sqs_even xs = [x*x | x <- xs, even x] -- number of list elements greater than 0 gt0 :: [Int] -> Int gt0 [] = 0 gt0 (x:xs) | x>0 = 1+gt0 xs | otherwise = gt0 xs -- II. Higher-order functions sum' :: [Int] -> Int sum' [] = 0 sum' (x:xs) = x+(sum' xs) foldr' :: (a -> b -> b) -> b -> [a] -> b foldr' f v [] = v foldr' f v (x:xs) = f x (foldr' f v xs) sum'' = foldr' (+) 0 foldl' :: (b -> a -> b) -> b -> [a] -> b foldl' f v [] = v foldl' f v (x:xs) = foldl' f (f v x) xs map' :: (a -> b) -> [a] -> [b] map' f [] = [] map' f (x:xs) = (f x):(map' f xs) -- Note: we can drop the argument on lhs and rhs sqs4 :: [Int] -> [Int] sqs4 = map' square where square x = x * x -- lambda abstractions sqs5 :: [Int] -> [Int] sqs5 = map' (\ x -> x*x) sqs_even' :: [Int] -> [Int] sqs_even' = map' (\ x -> x*x) . filter even -- curried functions add :: Int -> Int -> Int add x y = x + y inc :: Int -> Int inc x = x+1 incAll :: [Int] -> [Int] incAll = map' inc -- (+1) is a short-hand for (\ x -> x + 1) incAll' :: [Int] -> [Int] incAll' = map' (+1)