Solved problems : Higher Order Functions Pt. 2

Problem 8

Implement a function myReverse :: [Int] -> [Int] that reverses a list of integers.

myReverse [1..10]       -> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
myReverse [6, 2, 8, 4]  -> [4, 8, 2, 6]

We will use the functions flip and the function foldl

Example 1 Input: flip (/) 1 2 Output: 2.0

Example 2 Input: flip (>) 3 5 Output: True

myReverse :: [Int] -> [Int]
myReverse = foldl (flip (:)) []

Problem 9

Implement a function countIn :: [[Int]] -> Int -> [Int] that, given a list of sublists l and an element x, returns the list that tells how many times x appears in each sublist of l.

countIn [[3, 2, 3], [3], [], [2, 2]] 3      -> [2, 1, 0, 0]
countIn :: [[Int]] -> Int -> [Int]
countIn l x = map count l
    where
        count :: [Int] -> Int
        count = length . (filter (==x))

Problem 10

Implement a function firstWord :: String -> String that, given a string with blanks and alphabetic characters, returns its first word.

firstWord "    Good morning I say"          -> "Good"

We will use the functions dropWhile and takeWhile

Input : dropWhile (<3) [1, 2, 3, 4, 5] Output: [3, 4, 5]

Input : takeWhile (<3) [1, 2, 3, 4, 5] Output: [1, 2]

firstWord :: String -> String
firstWord = takeWhile (/= ' ') $ dropWhile (== ' ')

Problem 11

Define a function countIf :: (Int -> Bool) -> [Int] -> Int that, given a predicate on integers and a list of integers, returns the number of elements in the list that satisfy the predicate.

countIf (>5) [1..10]                        -> 5
countIf even [3, 4, 6, 1]                   -> 2

We will use the function filter

Input: filter (>5) [1, 2, 3, 4, 5, 6, 7, 8] Output: [6, 7, 8]

countIf :: (Int -> Bool) -> [Int] -> Int
countIf p x = length $ filter p x

Problem 12

Define a function combined :: [Int] -> [Int -> Int] -> [[Int]] that, given a list of integers and a list of functions from integers to integers, returns the list consisting of applying each of the functions in the second list to the elements in the first list.

Note: <- is an operator that means "belongs to".

combined [1, 2, 3] [(+1), (*2), (^2)]       -> [[2, 3, 4], [2, 4, 6], [1, 4, 9]]
                      f    f     f
             l            fs
combined :: [Int] -> [Int -> Int] -> [[Int]]
combined l fs = [map f l | f <- fs]

Problem 13

Define a function consecutive :: [Int] -> [Int -> Int] -> [[Int]] that, given a list of integers and a list of functions from integers to integers, returns the list of lists where each list if the result of applying, one after the other, the function in the second list to each element in the first list.

consecutive [1, 2, 3] [(+1), (*2), (^2)]    -> [[2, 2, 1], [3, 4, 4], [4, 6, 9]]
consecutive :: [Int] -> [Int -> Int] -> [[Int]]
consecutive l fs = [[f x | f <- fs] | x <- l]

Problem 14

Define a function

filterFoldl :: (Int -> Bool) -> (Int -> Int -> Int) -> [Int] -> Int
                 predicate        binary operator       list   result

that returns a fold of all the elements that satisfy the given predicate.

filterFoldl even (*) 1 [4, 7, 2, 4, 9, 3]   -> 32
filterFoldl :: (Int -> Bool) -> (Int -> Int -> Int) -> [Int] -> Int
filterFoldl cond f x0 l = foldl f x0 $ filter cond l