Higher Order Functions and Lists Solutions
Question: Writing List Recursion Functions
Here are some questions to help you revise list recursion. Note that the Answers are just one of many possible implementations.
- Implement the function
addOne :: [Int] -> [Int]
which takes a list and adds one to each element. E.gaddOne [1, 2] = [2, 3]
.
Answer:
addOne :: [Int] -> [Int]
addOne [] = []
addOne (x:xs) = (x + 1) : (addOne xs)
- Implement the function
multiplyN :: Int -> [Int] -> [Int]
which takes a list and multiplies each element by a constant somultiplyN 3 [1, 2] = [3, 6]
.
Answer:
multiplyN :: Int -> [Int] -> [Int]
multiplyN n [] = []
multiplyN n (x:xs) = (x * n) : (multiplyN n xs)
- Implement the function
addList :: (Num a) => [a] -> [a] -> [a]
which takes two lists and adds each element to the corresponding element in the other list, soaddList [3, 5] [1, 2] = [4, 7]
. Note thataddList
should produce an error if the lists have different lengths.
Answer:
addList :: (Num a) => [a] -> [a] -> [a]
addList l1 l2 = case (l1, l2) of
([], []) -> []
(x:xs, y:ys) -> (x + y) : (addList xs ys)
_ -> error "Lists do not have the same length"
- Implement the function
removeNegative :: [Int] -> [Int]
which takes a list and removes all the negative elements, soaddList [1, -2, 3, -4] = [1, 3]
.
Answer:
removeNegative :: [Int] -> [Int]
removeNegative [] = []
removeNegative (x:xs)
| x < 0 = removeNegative xs
| otherwise = x : (removeNegative xs)
Questions: Type Signatures for Higher Order Functions
Below, we have a variety of function definitions. All of these define higher order functions. For each, add the type signature. Remember to use polymorphism to make them as general as possible!
apply :: ____________
apply f x = f x
Answer:
apply :: (a -> b) -> a -> b
curry :: ____________
curry f x y = f (x,y)
Answer:
curry :: ((a,b) -> c) -> a -> b -> c
multiplyTwice :: ____________
multiplyTwice n = (\x -> x * n * n)
Answer:
multiplyTwice :: (Num a) => a -> (a -> a)
Questions: Type Signatures to Function Definition
Now we have the opposite: a lot of type signatures but no function definitions! Fill in the blanks and define the functions below based on their names, inputs and type signatures:
add :: Int -> (Int -> Int)
add n = ____________
Answer:
add n = (\x -> x + n)
choose :: Int -> [a -> b] -> a -> b
choose i listOfFunctions x = ____________
Answer:
choose i listOfFunctions x = (listOfFunctions !! i) x
Questions: Your Own Higher Order Function
Write the type signature for and define a higher order function that does the following: takes in two functions and a tuple and then applies the first function to the left tuple value and the second function to the right tuple value. This will return a tuple. For example:
func (+1) toUpper (0, 'i') = (1, I)
Answer:
func :: (a -> b) -> (c -> d) -> (a,c) -> (b,d)
func f1 f2 (a,b) = (f1 a, f2 b)
Questions: Writing Higher Order Functions on Lists
Now that you have some familiarity with higher order functions which operate on lists, have a go at writing your own version of the functions! Do this for map
, zipWith
, foldl
and foldr
.
Answers:
map :: (a -> b) -> [a] -> [b]
map f ls = case ls of
[] -> []
(x:xs) -> f x : map f xs
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipwith f (x:xs) (y:ys) = (f x y) : (zipwith f xs ys)
zipwith _ _ _ = []
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl f z ls = case ls of
[] -> z
(x:xs) -> foldl f (f z x) xs
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f z ls = case ls of
[] -> z
(x:xs) -> f x (foldr f z xs)