# Part 3 - Exercises 1. Show how the list comprehension `[x ^ 2 | x <- [1..20], even x]` can be re-expressed using the higher-order functions `map` and `filter`. 1. Show how, in general, a list comprehension of the type `[f x | x <- xs, p x]` can be expressed in a single function using `map` and `filter`. Use the function composition operator (`$`) to avoid parenthesis. ```haskell process :: (a -> b) -> (a -> Bool) -> [a] -> [b] process f p xs = undefined ``` 1. Re-write the `process` function above in pointfree style using the function composition operator (`.`). 1. Define a recursive function `sumdown` that returns the sum of the non-negative integers from a given value down to zero. For example, `sumdown 3` should return 6, and `sumdown (-1)` should return 0. ```haskell sumdown :: Int -> Int sumdown = undefined ``` 1. Suppose that a two-dimensional coordinate grid of size `n x m` is given by the list of all pairs of integers (x,y) such that `0 <= x <= n` and `0 <= y <= m`. Using list comprehension define a function `grid` that returns a coordinate grid of a given size. For example, `grid 1 2` should return `[(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]`. ```haskell type Position = (Integer, Integer) grid :: Integer -> Integer -> [Position] grid n m = undefined ``` 1. Using list comprehension and the function `grid` above, define a function `square` that returns a coordinate square of size `n`, excluding the diagonal positions from `(0,0)` to `(n,n)`. For example, `square 2` should return `[(0,1),(0,2),(1,0),(1,2),(2,0),(2,1)]`. ```haskell square :: Integer -> [Position] square n = undefined ``` 1. Using recursion, implement your own versions of the following list functions. Use the alternative names below to avoid conflicting with the functions included in Prelude. ```haskell -- replicate replicate' :: Int -> a -> [a] replicate' = undefined -- elem elem' :: Eq a => a -> [a] -> Bool elem' = undefined -- takeWhile takeWhile' :: (a -> Bool) -> [a] -> [a] takeWhile' = undefined -- dropWhile dropWhile' :: (a -> Bool) -> [a] -> [a] dropWhile' = undefined -- concat concat' :: [[a]] -> [a] concat' = undefined -- indexing operator (!!) (!!!) :: [a] -> Int -> a (!!!) = undefined ``` 1. Define a recursive function that merges two sorted lists to give a single sorted list. For example, `merge [2,5,6] [1,3,4]` should return `[1,2,3,4,5,6]`. ```haskell merge :: Ord a => [a] -> [a] -> [a] merge = undefined ``` 1. `reverse` is a function that returns the elements of a list in reverse order. Implement two versions of `reverse`, one using `foldr` and one using `foldl`. ```haskell reverseR :: [a] -> [a] reverseR = undefined reverseL :: [a] -> [a] reverseL = undefined ``` 1. Consider a binary search tree where each node has a unique value that is greater the values on its left branch, and less than the values on its right branch. Such a tree could be represented with the following data declaration: ```haskell data BSTree a = Leaf | Node (BSTree a) a (BSTree a) deriving (Show, Eq, Ord) ``` For example, the tree depicted below, with leafs shown as dots (`.`), 10 / \ 5 15 / \ / \ 2 6 * 19 / \ / \ / \ * * * * 17 22 / \ / \ * * * *` could be represented as follows: ```haskell bst = Node (Node (Node Leaf 2 Leaf) 5 (Node Leaf 6 Leaf)) 10 (Node Leaf 15 (Node (Node Leaf 17 Leaf) 19 (Node Leaf 22 Leaf))) ``` Given the `BSTree` data declaration above, write the function `occurs` that verifies if a given value is present in a tree, taking advantage of the properties of a binary search trees. When implemented correctly, `filter (flip occurs bst) [1..30]` should return `[2,5,6,10,15,17,19,22]`. ```haskell occurs :: Ord a => a -> BSTree a -> Bool occurs = undefined ``` 1. Write a function `insert` that inserts a new value into a binary search tree as defined above, if the value is not yet present. ```haskell insert :: Ord a => a -> BSTree a -> BSTree a insert = undefined ```