Solved problems : Higher Order Functions

Problem 1

Implement a function eql :: [Int] -> [Int] -> Bool that tells whether two lists of integers are equal.

eql [1, 2, 3] [1, 2, 3]     -- True
eql [1, 2, 3] [3, 2, 1]     -- False
eql [1, 2, 3] [1, 2, 3, 4]  -- False
eql :: [Int] -> [Int] -> Bool

eql x y
    | length x /= length y = False
    | otherwise = and $ zipWith (==) x y

-- With the dollar sign, we can make sure that the list is first built by zipWith, before the function 'and' is applied.

Problem 2

Implement a function prod :: [Int] -> Int that returns the product of a list of integers. (custom implementation of product)

prod [2, 10, 5]     -- 100
prod [3, 1, 2, 4]   -- 24

We will use an important function from Haskell : foldl. L stands for left because we start folding with n from the left.

Type: (a -> b -> a) -> a -> [b] -> a Input: foldl (/) 64 [4, 2, 4] Output: 2.0

prod :: [Int] -> Int

prod x = foldl (*) 1 x

prod = foldl (*) 1 -- This is implicit notation

Problem 3

Implement a function prodEvens :: [Int] -> Int that returns the product of all even numbers of a list of integers.

prodEvens [2, 10, 5]    -- 20
prodEvens [3, 1, 2, 4]  -- 8
prod :: [Int] -> Int
prod = foldl (*) 1

prodEvens :: [Int] -> Int
prodEvens = prod . filter even      -- with implicit notation

prodEvens l = prod (filter even l)  -- explicit notation

Problem 4

Implement a function powersOf2 :: [Int] that generates that list of all the powers of 2.

take 5 powersOf2        -- [1, 2, 4, 8, 16]
take 3 powersOf2        -- [1, 2, 4]

There is a standard function called iterate which returns an infinite list.

powersOf2 :: [Int]
powersOf2 = iterate (*2) 1

Problem 5

Implement a function scalarProduct :: [Float] -> [Float] -> Float that returns the dot product of two lists of float numbers with the same size.

scalarProduct [2.0, 1.0, 5.0] [3.0, 2.0, 2.0] -- 18.0
scalarProduct [3.0, 4.0] [5.0, 3.0]           -- 27.0

We want to do:

l1 = [x, y, z]
l2 = [a, b, c]

dot product = x * a + y * b + z * c

-> l3 = [x * a, y * b, z * c]
sum l3
scalarProduct :: [Float] -> [Float] -> Float
scalarProduct x y = sum $ zipWith (*) x y

Problem 6

Implement a function flatten :: [[Int]] -> [Int] that flattens a list of lists of integers in a list of integers.

flatten [[1, 2, 3], [4, 5], [6], [], [3, 3]] -- [1, 2, 3, 4, 5, 6, 3, 3]
flatten [[2, 7], [8, 9], []]                 -- [2, 7, 8, 9]
flatten :: [[Int]] -> [Int]
flatten = foldr (++) []         -- implicit input

flatten x = foldr (++) [] x     -- explicit input

Problem 7

Implement a function myLength :: String -> Int that returns the length of a string.

myLength "Tomas"                -- 5
myLength "Sunset"               -- 6
myLength :: String -> Int
myLength = foldr (+) 0 . map (const 1)