1.) Determine the type of each of these values. (Many of the types will be polymorphic, that is, you need to use type variables to describe the type.) a) Just "cat" b) Nothing c) [Just "dog", Nothing] d) [Nothing, Nothing] e) Just (Just "cat") f) Left "car" g) Right (Just "cat") h) Right (Left "dog") i) Right (Left (Right "can")) j) [(3, Just "dog"), (1, Nothing)] k) [(Left "cat", Just "dog")] l) (Right "cat", Nothing) m) [Right "cat", Left 2.3] n) [Just 2, Just 3.4] o) (Just 2, Just 3.4) p) Just '+' q) Just (+) r) Right tail s) [Left head, Right tail] t) (Left head, Right tail) u) Just [] v) Just Nothing w) Just (Left Nothing) 2.) This problem will use the following data type. data IorD = I Integer | D Double deriving Show Use this list for testing. iord = [I 1, D 1, D 2.1, I 0, D 3.4, D 5.6, D 0, I (-2), I 3, D (-5.4)] Write definitions for each of the following functions. a) Extract the integers from a list of IorD. extractI :: [IorD] -> [Integer] b) Extract the doubles from a list of IorD. extractD :: [IorD] -> [Double] c) Extract the integers from a list of IorD but replace each double with Nothing. Write this function two ways, using recursion, and using the map function. extractIM :: [IorD] -> [Maybe Integer] d) Extract the doubles from a list of IorD but replace each integer with Nothing. Write this function two ways, using recursion, and using the map function. extractDM :: [IorD] -> [Maybe Double] e) Extract a list of integers and a list of doubles from a list of IorD. Don't write this function using extractI and extractD because that will be inefficient (why?). Write this as a function recursively. extractID :: [IorD] -> ([Integer], [Double]) f) Extract a list of Maybe Integer and a list of Maybe Double from a list of IorD. Don't write this function using extractIM and extractDM because that will be inefficient. extractIDM :: [IorD] -> ([Maybe Integer], [Maybe Double]) 3.) Describe the difference between the type Maybe [a] and the type [Maybe a] 4.) Describe the difference between the type Either [a] [b] and the type [Either a b] 5.) Describe the difference between the type Maybe (a, b) and the type (Maybe a, Maybe b) 6.) Suppose you have the following types. type A = Maybe Integer type B = Maybe A type C = Maybe B type D = Maybe C Write a function getA :: D -> Maybe Integer that consumes a D value and tries to follow the chain of values to get to the integer in the A. But if any of the intervening values are Nothing, getA should return Nothing. getA (Just (Just (Just (Just 5)))) ==> Just 5 getA (Just (Just Nothing)) ==> Nothing getA (Just Nothing) ==> Nothing Note: You can define getA two ways, using pattern matching equations, or using nested case-expressions. 7.) Use data to define a datatype Quadruple which holds four elements with the first two elements having the same type and the last two elements having the same type. Write a function firstTwo which consumes a Quadruple value and returns a list containing the first two elements. Write a function lastTwo which consumes a Quadruple value and returns a list containing the last two elements. Give type signatures for these two functions. firstTwo (Q 1 2 "cat" "dog") ==> [1,2] lastTwo (Q 1 2 "cat" "dog") ==> ["cat","dog"] 8.) Use data to define a datatype Tuple which can hold one, two, three or four elements, depending on the constructor (that is, there should be four constructors, one for each number of arguments). Also provide functions tuple1 through tuple4 which consume a Tuple value and return Just the value in that position, or Nothing if the number is invalid (i.e., you ask for the tuple4 on a Tuple value holding only two elements). Give type signatures for these four functions. 9.) Define a function that swaps the order of an Either. twist :: Either a b -> Either b a 10.) Define the following two functions. join1 :: (a -> c) -> (b -> c) -> Either a b -> c join2 :: (a -> c) -> (b -> d) -> Either a b -> Either c d join1 length (+5) (Left "cat") ==> 3 join1 length (+5) (Right 2) ==> 7 join2 length even (Left [1,2,3]) ==> Left 3 join2 length even (Right 3) ==> Right False 11.) Write the following version of the take function. takeM :: Int -> [a] -> [Maybe a] where takeM will pad the output list with Nothings if the input list is not long enough. 12.) Here are three definitions for three kinds of binary trees. data BTree1 a = Leaf1 a | Branch1 (BTree1 a) (BTree1 a) data BTree2 a = Leaf2 | Branch2 a (BTree2 a) (BTree2 a) data BTree3 a b = Leaf3 a | Branch3 b (BTree3 a b) (BTree3 a b) (a) How would you explain to someone how these differ? Draw a few examples of each kind of binary tree. (b) This binary tree definition is weird (it combines aspects Btree1 and Btree2). What makes it a bit unusual? data BTree4 a = Tip4 | Leaf4 a | Fork4 (BTree4 a) (BTree4 a) | Branch4 a (BTree4 a) (BTree4 a) (Hint: Which of the above types of binary trees can be "empty", that is, not hold any data? Can BTree4 be empty?) (c) Write the function that adds up the numbers in an integer BTree1. sumBTree1 :: BTree1 Integer -> Integer sumBTree1 (Branch1 (Leaf1 4) (Branch1 (Leaf1 4) (Leaf1 2))) ==> 10 (d) Write the function that adds up the numbers in an integer BTree2. sumBTree2 :: BTree2 Integer -> Integer sumBTree2 (Branch2 4 (Leaf2) (Branch2 3 (Leaf2) (Leaf2))) ==> 7 sumBTree2 (Branch2 4 (Leaf2) (Branch2 3 (Branch2 5 Leaf2 Leaf2) (Leaf2))) ==> 12