2018-11-18 21:50
Page 1

Page 2

# Announcement

## Drop-in office hours

• Starting in Week 3, the teaching assistants have open office hours when you can drop in and ask questions about the lab assignments.
• See the schedule for the drop-in office hours on the course home page.
Page 3

# What is a higher order function?

• It's a function that takes another function as an argument.
• `even 1` False `even 2` True `map even [1,2,3,4,5]` [False,True,False,True,False] `filter even [1,2,3,4,5]` [2,4]
• `even` is a first-order function.
• `map` and `filter` are higher-order functions.
Page 4

# The types of higher order functions

• ```map    :: (a -> b)    -> [a] -> [b]
filter :: (a -> Bool) -> [a] -> [a]
```
• The first argument is a function in both cases.
• They are also polymorphic. This is a powerful combination!
Page 5

# Is this a big deal?

• Yes!
• Higher-order functions are the "heart and soul" of functional programming!
• A higher-order function can be much more versatile than a first-order function, because a part of its behaviour can be controlled by the caller.
• Many similar first-order functions can be replaced by one higher-order function, factoring out the difference into a function argument.
Page 6

Page 7

# Passing functions as arguments

• Sometimes the function we want to pass as an argument to a higher-order function is already defined and has a name, e.g.
• ```filter even [1..5] == [2,4]
```
• But what if it isn't?
• We can solve it by defining a helper function.
• ```squares = map square [1..5]
where square x = x*x```
• Let's also look at some other convenient way to create functions.
Page 8

# Partial application

• We can apply functions to "too few" arguments
• `take 2 "Haskell"` "Ha" `map (take 2) ["Hello","Haskell"]` ["He","Ha"]
• The advantage with curried functions reveals itself!
Page 9

# Partial application of infix operators

• Operators can be used as functions by omitting one operand.
• `5*3 == 15`
• `(*3) 5 == 15`
• `map (*3) [1..5] == [3,6,9,12,15]`
• `filter (<3) [1..5] == [1,2]`
• `filter (3<) [1..5] == [4,5]`
• This is called sections.
Page 10

# Function composition

• Example: remove white space from a string
• `removeSpaces "abc def \n ghi" = "abcdefghi"`
• We can use `isSpace` from module `Data.Char`,
• `removeSpaces s = filter (not . isSpace) s`
• Function composition is defined as
• ```(f . g) x = f (g x)
```
• What is the type of (.)?
Page 11

# Anonymous functions

• So far we have defined functions by equations where the function parameters appears on the left hand side. But there is another way:
• ``` --square x = x*x
square = \ x -> x*x```
• If we are going to use a function only in one place, we can use it directly without giving it a name first
• ```squares = map square numbers
where square x = x*x
numbers = [1..5]
```
• ```squares = map (\x -> x*x) [1..5]
```
• We have the same choice for functions as for any other type of value.
• The \ is supposed to look a bit like a λ (the greek letter lambda) and comes from the λ-calculus, where functions are always written in this way.
Page 12

# Functions returning functions?

• If passing functions as arguments is powerful, how about returning functions as results?
• Compare these types:
1. `Int -> Int -> Int`
2. `Int -> (Int -> Int)`
3. `(Int -> Int) -> Int`
• Which of these types are equal, which are different?
Page 13
##### Functions returning functions?
`Int -> Int -> Int`
is the same as
`Int -> (Int -> Int)`
• These are the same:
• A function that takes two argument
• A function that takes one argument and returns a function that takes one argument.
• Another example: function composition
• `(b->c)->(a->b)->(a->c)`
• `(b->c)->(a->b)-> a->c`
Page 14

# Curried functions

• Compare these types:
1. `Int -> Int -> Int`
2. `(Int,Int) -> Int`
• Both are in effect functions that take two
`Int`
s and return an
`Int`
.
• We have seen that Haskell favours the first variant.
• Such functions are called curried functions, after the logician Haskell Curry.
• Incidentally (or not) the Haskell language is also named after Haskell Curry.
• The predefined functions
`curry`
and
`uncurry`
convert between the two forms.
Page 15

## Uncurried vs curried functions as tables

• In math, functions are sometimes illustrated as tables (example)
• (Int,Int)->Int
InOut
(1,1)2
(1,2)3
(2,1)3
(2,2)4
Int->Int->Int
InOut
1
In Out
12
23
2
In Out
13
24
Page 16

# Defining higher order functions

## First examples

• ```map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x:map f xs```
• ```filter :: (a -> Bool) -> [a] -> [a]
filter p [] = []
filter p (x:xs) | p x       = x:filter p xs
| otherwise = filter p xs```
Page 17

# Case study: sums and products of lists

• ```sum []     = 0
sum (x:xs) = x + sum xs```
• ```product []     = 1
product (x:xs) = x * product xs```
• Common pattern: combining the elements of a list with an operator
• Differences: the operator and the base case.
Page 18

# Factoring out the differences

• ```foldr op base [] = base
foldr op base (x:xs) = x `op` foldr op base xs```
• Note:
`x `f` y`
is the same as
`f x y`
• What is the type of foldr?
• `foldr :: (a -> b -> b) -> b -> [a] -> b`
• `foldr` is also known as reduce. You already know `map`, so now you know the essence of MapReduce!
Page 19

# Code reuse

• We can now simplify the definitions of sum and product.
• ```sum     xs = foldr (+) 0 xs
product xs = foldr (*) 1 xs```
• And `foldr` is useful in many more cases!
• ```or     xs = foldr (||) False xs
and    xs = foldr (&&) True xs
concat xs = foldr (++) [] xs

maximum (x:xs) = foldr max x xs```
• These are all examples of predefined functions in Haskell.
Page 20

• Think of
`foldr (&) z`
(where
`&`
is some operator) as function that • replaces
`:`
with
`&`
, and
• replaces
`[]`
with
`z`
.
• `            xs == a : b : c : d : … : []`

`foldr (&) z xs == a & b & c & d & … & z`

`foldr (+) 0 xs == a + b + c + d + … + 0`

`foldr (*) 1 xs == a * b * c * d * … * 1`
Page 21

# Quiz

## What does these function do?

• `f1 xs = foldr (:) [] xs`
• `f2 xs ys = foldr (:) ys xs`
• ```f3 xs = foldr snoc [] xs
where snoc x ys = ys++[x]
```
• ```f4 f xs = foldr fc [] xs
where fc x ys = f x:ys```
Page 22

# Example

• Combine a list of lines into a string with newline characters:
• `unlines ["abc","def","ghi"] = "abc\ndef\nghi\n"`
• One-line definition:
• `unlines ls = foldr (\xs ys->xs++"\n"++ys) [] ls`
• or with a named helper function:
• ```unlines ls = foldr join [] ls
where join xs ys = xs ++ "\n" ++ ys```
Page 23

# Eta conversion

• Consider definitions of the form
• `f x = g x`
• We are saying that f is the same function as g. This can be said in a simpler way
• `f = g`
• This is called Eta (η) conversion/reduction/expansion.
• Caveat: the monomorphism restriction in Haskell:
• A definition without parameters and without a type signature is not allowed to be overloaded.
Page 24

# Eta conversion examples

```or     = foldr (||) False
and    = foldr (&&) True
concat = foldr (++) []

removeSpaces = filter (not . isSpace)

unlines = foldr (\xs ys->xs++"\n"++ys) []
```
Page 25

# More standard higher-order functions

• Define
• `takeLine :: String -> String`
• such that
• `takeLine "abc\ndef\nghi\n" = "abc"`
• Generalize it to
• ```takeWhile :: (a->Bool) -> [a] -> [a]
```
• Also define the complementary
• ```dropWhile :: (a->Bool) -> [a] -> [a]
```
Page 26

# Lines

• Define
• ```lines :: String -> [String]
```
• such that
• ```lines "abc\ndef\nghi\n" = ["abc","def","ghi"]
```
• Generalize it to
• ```segments :: (a->Bool) -> [a] -> [[a]]
```
Page 27

# Words

• Define
• ```words :: String -> [String]
```
• such that
• ```words "abc def  ghi" = ["abc","def","ghi"]
```
Page 28

# A bigger example: word counting

• Define a function that counts how many times words occur in a text and displays each word with its count.
• `wordCounts :: String -> String`
• `putStr (wordCounts "hello clouds\nhello sky")` clouds: 1 hello: 2 sky: 1
• Source code: HigherOrderFunctions.hs, towards the bottom of the file.
Page 29

# Lessons

• Higher-order functions take functions as arguments, making them flexible and useful in many situations.
• By writing higher-order functions to capture common patterns, we can reduce the amount of code we need to write dramatically.
• Anonymous functions, partial applications, function composition and sections help us create functions to pass as arguments, often eliminating the need for a separate function definition.
• Haskell provides many useful higher-order functions;
• break problems into small parts, each of which can be solved by an existing function.
Page 30

# Higher order functions in other languages?

• Consider these generic sorting functions in Haskell:
• ```sort   :: Ord a            => [a] -> [a]
sortBy :: (a->a->Ordering) -> [a] -> [a]
```
• Compare with a generic sorting function in C:
• void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
Page 31

# Extra

## Quiz

### How many arguments do the following functions have?

• ```pick 1 = fst
pick 2 = snd```
• `id :: a -> a`