Almost all of these problems ask you to write a recursive function. 1.) Write a recursive function makeList :: Int -> a -> [a] that consumes an integer n and an item x and returns a list of length n, each element of which is the item x (if n is negative, return the empty list). 2.) (a) Write a recursive function copy :: [a] -> [a] that returns a copy of its list argument. (b) Write a recursive function copyNum :: (Num a, Ord a) => [a] -> [a] that returns a copy of its list argument except that every negative number should be replaced with 0. 3.) Write a recursive function count :: Eq a => a -> [a] -> Int that counts the number of times its first argument appears in its list argument. 4.) Write a recursive function remove :: Eq a => a -> [a] -> [a] that removes all occurrences of its first argument from its list argument. 5.) (a) Write a recursive function everyOther :: [a] -> [a] that removes every other element of its list argument, starting with the first element. (b) What does this function do? mystery :: [a] -> [a] mystery [] = [] mystery (x:xs) = x : everyOther xs 6.) (a) Write a recursive function dropNth :: Int -> [a] -> [a] that removes the n'th element from the input list (the 0'th element is the first element). If n is negative, or greater than the length of the list, don't drop anything. (b) Write a recursive function addNth :: Int -> a -> [a] -> [a] that returns a list which has all the elements from the input list but it has the given input element as the new list's n'th element (the 0'th element is the first element). The new list will be one longer than the input list. If n is negative, put the input element at the beginning of the new list. If n is greater than the length of the input list, put the input element at the end of the new list. (c) Consider addNth as a curried function. Which would be a better way to define it, as addNth :: Int -> a -> [a] -> [a] or as addNth :: a -> Int -> [a] -> [a] Give a reason for your choice. (Hint: How might you use addNth as a partially applied function?) (d) Write a recursive function replaceNth :: Int -> a -> [a] -> [a] that returns a list which has all the elements from the input list except it has the given input element as the new list's n'th element (the 0'th element is the first element). The new list will be the same length as the input list. If n is negative, or greater than the length of the input list, then don't replace any element of the input list. (e) Consider the memeory allocation used in your implementations of dropNth, addNth, and replaceNth. For example, what exactly does your implementation do in these cases? dropNth 5 [0..1000] dropNth 995 [0..1000] addNth 5 0 [0..1000] addNth 995 0 [0..1000] addNth (-1) 0 [0..1000] addNth 1001 0 [0..1000] 7.) (a) Write a function between :: Int -> Int -> [a] -> [a] that consumes two integers n and m and returns the sub list of the input list starting at the n'th element and ending at the m'th element (inclusive). Write this function two ways. First, using Haskell's take and drop functions. Second, write it recursively without using take and drop. (b) Write a function excise :: Int -> Int -> [a] -> [a] that consumes two integers n and m and returns a list made of the first n-1 elements of the input list followed by the elements from the input list starting at index m+1. Write this function two ways. First, using Haskell's take and drop functions. Second, write it recursively without using take and drop. (Hint: You will probably need a recursive helper function.) 8.) Write a recursive function repeats :: Eq a => [a] -> Bool that returns true if and only if the input list has two equal elements next to each other. 9.) Write a recursive function swap :: [(a,b)] -> [(b,a)] that consumes a list of pairs and returns a list of pairs with each input pair's order being swapped. Note: A version of this was used as an example in class but it was written using pattern matching and a list comprehension. Here you should write it as a recursive function. 10.) Write a recursive function lookup' :: Eq a => a -> [(a,b)] -> b that consumes an element x and returns the second item from the first pair that contains x as its first item. If no pair contains x as its first item, return an error. 11.) (a) Write a recursive function merge :: Ord a => [a] -> [a] -> [a] which consumes two sorted lists and returns the sorted list that results from merging the two input lists. (Your function can assume that the input lists are sorted. It doesn't need to verify this.) (b) Write a recursive function split :: [a] -> ([a], [a]) which consumes a list and splits the list int two "halves". The return value is a pair of lists, each being about half the elements from the input list. The easiest way to do this is to have split put every other element from the input list, starting from the first element, into the first output list and put every other element from the input list, starting from the second element, into the second output list. (c) Check that the function mergesort :: Ord a => [a] -> [a] mergesort [ ] = [ ] mergesort [x] = [x] mergesort xs = merge (mergesort ys) (mergesort zs) where (ys,zs) = split xs really does sort a list. 12.) Write a recursive function union :: Eq a => [a] -> [a] -> [a] that mimics the union of sets. This function should consume two lists, that are each assumed to not contain any duplicate elements, and it should produce a list that "merges" the two input lists into a list that contains all the elements from the two input lists but without any duplication. The order of elements in the output list does not matter. Here are a couple of examples (your results need not have the same order). union "cats" "dogs" ==> "datcogs" union [0,4,3,6,1,9] [1,5,3,8] ==> [9,8,6,5,4,3,1,0] 13.) Write a recursive function prefix :: Eq a => [a] -> [a] -> Bool that returns true if the first list is the prefix of the second list. That is, the items from the first list appear as the initial segment of the second list. The empty list should be considered a prefix of every list. 14.) Write a recursive function subList :: Eq a => [a] -> [a] -> Bool that returns true if the first list is a sub list of the second list. That is, all the items from the first list appear consecutively, somewhere the second list. The empty list should be considered a sub list of every list. (Hint: Use prefix from the previous problem.) 15.) Write a recursive function subSeq :: Eq a => [a] -> [a] -> Bool that returns true if the first list is a sub sequence of the second list. That is, all the items from the first list appear sequentially (but not necessarily consecutively) in the second list. The empty list should be considered a sub sequence of every list. Here is an example. subSequence [2, 4, 6] [1, 2, 3, 4, 5, 6, 7] ==> True 16.) Write a recursive function everyNth :: Int -> [a] -> [a] that consumes an integer n and returns a list containing every n'th item from the input list. (Hint: Write a helper function or make use of drop.) 17.) Write a recursive function removeNths :: Int -> [a] -> [a] that consumes an integer n and removes from the input list every n'th item of the input list. (Hint: Write a helper function or make use of take.) 18.) Write an operator !!! which acts like Haskell's !! operator except that it also indexes from the right hand end of the list when given a negative index. So [1, 2, 3, 4, 5, 6, 7] !!! (-2) should return 6 (so index -1 is the last element of the list). (Hint: Write !!! in terms of !!.) 19.) Write a function zip3' :: [a] -> [b] -> [c] -> [(a,b,c)] that zips together three lists. Write this two ways. One way making use of the zip function and another way that is recursive and doesn't use zip. 20.) Write your own implementations, inits' and tails', of Haskell's inits and tails functions. https://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:inits https://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:tails 21.) The zip function has type zip :: [a] -> [b] -> [(a,b)] and the unzip function has type unzip :: [(a,b)] -> ([a],[b]) Notice that the unzip function does not give you back what you started with when you called the zip function because zip takes as input two lists, but unzip gives you back a pair of lists (and a pair of lists is not the same thing as two lists). Write a recursive function un_unzip that takes in a pair of lists and zips the two lists into a list of pairs. un_unzip :: ([a],[b]) -> [(a,b)] If z is a list of pairs, then un_unzip (unzip z) should return exactly z. If w is a pair of lists, should unzip (un_unzip w) return w? 22.) Write a recursive function flatten :: [[a]] -> [a] that consumes a list of lists and creates a list containing all the items from the original list's nested lists in the same order that they appeared in the original list. Here is an example. flatten [[3,2,1],[1,2,3],[7],[],[5,6]] ==> [3,2,1,1,2,3,7,5,6] 23.) Write a recursive function heads :: [[a]] -> [[a]] that consumes a list of lists and returns a list of lists where each non empty nested list of the original list is shortened to just its first element in the output list and empty nested lists are empty lists in the output list. Here is an example. heads [[3,2,1],[1,2,3],[7],[],[5,6]] ==> [[3],[1],[7],[],[5]] 24.) (a) Write a function plist :: Int -> [a] -> [a] that consumes an integer n and a list and returns a list that repeats the input list n times. The name "plist" is an abbreviation of "periodic list". Here is an example. plist 5 [1,2,3] ==> [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3] (b) This part is similar to the previous part. Write a function plist' :: Int -> [a] -> [a] that consumes an integer n and a list and returns a list of length n that repeats the elements from the input list n times. The name "plist" is (again) an abbreviation of "periodic list". Here is an example. plist' 17 [1,2,3] ==> [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2]