# Haskell: Higher Order Functions (Part I)¶

Note

These slides are also available in PDF format: 4:3 PDF, 16:9 PDF, 16:10 PDF.

## Review: Functions are Data¶

Haskell lets us pass functions as the arguments to other functions:

double :: (Num a) => a -> a
double x = x * 2

doubleAll :: (Num a) => [a] -> [a]
doubleAll xs = map double xs


And we can define functions which take functions:

map' :: (a -> b) -> [a] -> [b]
map' _ [] = []
map' f (x:xs) = f x : map f xs


We see Haskell treats functions as a first-class citizen; that is, we can pass them around just like any other type of data.

## Review: Currying¶

• Haskell takes advantage of currying to support functions with multiple arguments. That is, functions take a single argument and return a function ready to take the next argument.
• We call the function ready to take the next argument a partially applied function.

subtractMinutes :: Int -> Int -> Int
subtractMinutes n x = (x - n) mod 60

-- define a function which subtracts
-- 45 minutes every time
--      subtract45 30 --> 45
subtract45 = subtractMinutes 45


## Partially Applied Prefix Functions¶

multiplyBy :: (Num a) => a -> a -> a
multiplyBy x y = x * y

-- define our doubleAll using a partially applied
-- prefix function (and currying!)
doubleAll = map (multiplyBy 2)


## Partially Applied Infix Functions¶

Write a partially complete infix function in parentheses to create a partially applied infix function.

-- define our doubleAll using a partially applied
-- infix function (and currying!)
doubleAll = map (2 *)

-- also valid
doubleAll = map (* 2)


## zipWith¶

zipWith is a really useful function in Haskell’s standard library. It takes a function that takes two arguments, and applies it to two each of the elements from two lists. For example:

GHCi> zipWith (+) [1,2,3] [10,20,30]
[11,22,33]
GHCi> zipWith max [1..5] (reverse [1..5])
[5,4,3,4,5]


## Let’s Implement zipWith¶

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys


## Anonymous Functions (Lambdas)¶

Haskell provides a notation to write functions inline without a name:

-- twistTuples [(1,2),(3,4)] --> [(2,1),(4,3)]
twistTuples xs = map (\ (a,b) -> (b,a)) xs


Why do we have lambdas? Perhaps there is a case where writing a lambda might be cleaner than another function, a let or where binding, or partial application.

## Maybe Lambda Makes This Cleaner¶

Perhaps a lambda can make it more clear we are returning another function. Consider the flip function (in Haskell’s standard library) which takes a function and returns a new one with the arguments flipped:

flip' :: (a -> b -> c) -> b -> a -> c
flip' f x y = f y x


Is it immediately obvious this function is supposed to return another (partially applied) function? Compare to this definition:

flip' :: (a -> b -> c) -> b -> a -> c
flip' f = \ x y -> f y x


## Quiz Prep Time¶

With your learning groups, everyone take turns taking your quizzes you designed. Once finished, we will start Quiz 2.

More on higher order functions next time.