====== 4. Higher order functions ======
===== 4.1. Map, foldl, foldr, filter, zipWith =====
==== Map ====
The function ''map'' has signature: ''(a->b) -> [a] -> [b]''. It takes as parameter:
- a **transformer** function ''f :: a->b''
- a list of objects of type ''a''
It returns:
- a list of transformed objects of type ''b''
4.1.1. Write a function which takes a list of integers and adds 4 to **each element**.
4.1.2. Write a function which takes a list of strings and adds a whitespace at the **beginning** of each string.
4.1.3. Write a function which takes a value k, a list of **strings** and returns a list with the first k characters of each string.
==== Filter ====
The function ''filter :: (a -> Bool) -> [a] -> [a]'' takes as parameter:
* a **predicate** (or condition) of type ''(a -> Bool)''
* a list of elements of type ''a''
It returns:
* a list of filtered elements using the predicate.
4.1.4. Write a function which removes all strings which are equal to the empty string.
4.1.5. Write a function which takes a list of strings and returns only those which start with a capital.
==== Foldr ====
The function ''foldr'' has type ''(a -> b -> b) -> b -> [a] -> b''. It takes as parameter:
* a **binary** operation ''a -> b -> b''. It takes a "list" element of type ''a'', and an **accumulator** of type ''b'' and returns an element of type ''b''
* an **accumulator** (or initial value) of type ''b''
* a list with elements of type ''a''
It returns:
* a **folded** (or reduced) value of type ''b''.
Example:
foldr (*) 0 [1,2,3] = 1 * (2 * (3 * 0))
4.1.6. Write a function using foldr which computes the product of a list of integers.
4.1.7. Write a function which computes the maximum of a list of **positive** integers using foldr.
4.1.8. Write a function which concatenates a list of strings using foldr.
==== Foldl ====
The function ''foldl'' has type ''(b -> a -> b) -> b -> [a] -> b''. It takes as parameter:
* a **binary** operation ''b -> a -> b''. It takes an **accumulator** of type ''b'', a "list" element of type ''a'' and returns an element of type ''b''
* an **accumulator** (or initial value) of type ''b''
* a list with elements of type ''a''
It returns:
* a **folded** (or reduced) value of type ''b''.
Unlike foldr, foldl reduces element in a different order:
Example:
foldl (*) 0 [1,2,3] = ((0 * 1) * 2) * 3
4.1.9. Write a function which uses foldl to check if an element is member of a list.
4.1.10. Write a function which uses foldl to implement the reversal of a list.
==== zipWith ====
4.1.11. Use ''ghci> :t zipWith'' to inspect the type of ''zipWith''. Think about a possible example to run this function. What does it do?