Joseph Haugh
University of New Mexico
What is a first class function?
What is an operator section?
What will the following code evaluate to?
(*2) ((+1) 3)
8
What is currying?
What is the type of the take
function?
take :: Int -> [a] -> [a]
What is the type of the following expression?
take 10
[a] -> [a]
Implicitly curried:
add :: Int -> Int -> Int
add x y = x + y
Explicitly curried:
add :: Int -> (Int -> Int)
add = \x -> (\y -> x + y)
Implicitly curried:
add :: Int -> Int -> Int
add x y = x + y
take :: Int -> [a] -> [a]
take n xs = ...
Explicitly curried:
add :: Int -> (Int -> Int)
add = \x -> (\y -> x + y)
take :: Int -> ([a] -> [a])
take = \n -> (\xs -> ...)
Implicitly curried:
add :: Int -> Int -> Int
add x y = x + y
take :: Int -> [a] -> [a]
take n xs = ...
foo ::
(a -> b) -> (a, a) -> (b, b)
foo f (x, y) = ...
Explicitly curried:
add :: Int -> (Int -> Int)
add = \x -> (\y -> x + y)
take :: Int -> ([a] -> [a])
take = \n -> (\xs -> ...)
foo ::
(a -> b) -> ((a, a) -> (b, b))
foo = \f -> (\(x, y) -> ...)
Implicitly curried:
add :: Int -> Int -> Int
add x y = x + y
take :: Int -> [a] -> [a]
take n xs = ...
foo ::
(a -> b) -> (a, a) -> (b, b)
foo f (x, y) = ...
hyper :: Int -> Integer ->
Integer -> Integer
hyper x m n = ...
Explicitly curried:
add :: Int -> (Int -> Int)
add = \x -> (\y -> x + y)
take :: Int -> ([a] -> [a])
take = \n -> (\xs -> ...)
foo ::
(a -> b) -> ((a, a) -> (b, b))
foo = \f -> (\(x, y) -> ...)
hyper :: Int -> (Integer ->
(Integer -> Integer))
hyper = \x -> (\m -> (\n -> ...))
All of the previous examples are equivalent, since Haskell functions are curried by default.
Understanding this is crucial to understanding how to use higher order functions.
twice :: (a -> a) -> a -> a
twice f x = f (f x)
> twice (*3) 3
twice :: (a -> a) -> a -> a
twice f x = f (f x)
> twice (*3) 3
27
> twice (take 2) [1..10]
twice :: (a -> a) -> a -> a
twice f x = f (f x)
> twice (*3) 3
27
> twice (take 2) [1..10]
[1,2]
> twice (twice (*3)) 3
twice :: (a -> a) -> a -> a
twice f x = f (f x)
> twice (*3) 3
27
> twice (take 2) [1..10]
[1,2]
> twice (twice (*3)) 3
243
twice :: (a -> a) -> a -> a
twice f x = f (f x)
twice (twice (*3)) 3
| { applying outer twice }
twice (*3) (twice (*3) 3)
| { applying outer twice }
(*3) ((*3) (twice (*3) 3))
| { applying inner twice }
(*3) ((*3) ((*3) ((*3) 3)))
| { applying (*3)s }
243
map (+1) [1,2,3]
map (+1) [1,2,3]
[2,3,4]
map (*2) [1,2,3]
map (+1) [1,2,3]
[2,3,4]
map (*2) [1,2,3]
[2,4,6]
map (take 2) ["hello", "world", "goodbye"]
map (+1) [1,2,3]
[2,3,4]
map (*2) [1,2,3]
[2,4,6]
map (take 2) ["hello", "world", "goodbye"]
["he", "wo", "go"]
What does map do?
What is map
’s type?
Map applies a unary function to each element of a list.
map :: (a -> b) -> [a] -> [b]
Try to implement map'
.
map' :: (a -> b) -> [a] -> [b]
Step 1: Define the type, done. Step 2: Enumerate the cases:
map' :: (a -> b) -> [a] -> [b]
map' f [] = ...
map' f (x:xs) = ...
Step 3: Define the simple cases:
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = ...
Step 4: Define the other cases:
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = f x : map' f xs
Step 5: Generalize and simplify:
Can you do it with a list comprehension?
map' :: (a -> b) -> [a] -> [b]
map' f xs = [f x | x <- xs]
Step 6: Test your function:
> map' (+1) [1,2,3]
[2,3,4]
> map' (*2) [1,2,3]
[2,4,6]
> map' (take 2) ["hello", "world", "goodbye"]
["he", "wo", "go"]
What does this expression evaluate to?
map (map (+1)) [[1,2,3], [4,5]]
What does this expression evaluate to?
map (map (+1)) [[1,2,3], [4,5]]
| { applying outer map }
[map (+1) [1,2,3], map (+1) [4,5]]
| { applying inner maps }
[[2,3,4], [5,6]]
> filter even [1..10]
[2,4,6,8,10]
> filter (>5) [1..10]
[6,7,8,9,10]
> filter (== 'a') "banana"
"aaa"
What does filter
do?
What is filter
’s type?
Filter selects elements from a list that satisfy a predicate.
filter :: (a -> Bool) -> [a] -> [a]
filter :: (a -> Bool) -> [a] -> [a]
filter pred xs = [x | x <- xs, pred x]
How can we define filter
using direct recursion?
filter :: (a -> Bool) -> [a] -> [a]
filter pred [] = []
filter pred (x:xs)
| pred x = x : filter pred xs
| otherwise = filter pred xs
Define a function sumOddCubes
that takes a list of integers and returns the sum of the cubes of the odd numbers in the list. You must use map
and filter
and no list comprehensions or explicit recursion.
sumOddCubes :: [Int] -> Int
sumOddCubes :: [Int] -> Int
sumOddCubes xs = sum (map (^3) (filter odd xs))
What if you did do it with list comprehensions?
sumOddCubes :: [Int] -> Int
sumOddCubes xs = sum [x^3 | x <- xs, odd x]
Notice the similarities, the expression on the left hand side
of the |
is the map
expression and the guard expression
is the filter
expression.
What about with explicit recursion?
sumOddCubes :: [Int] -> Int
sumOddCubes [] = 0
sumOddCubes (x:xs)
| odd x = x^3 + sumOddCubes xs
| otherwise = sumOddCubes xs
> all even [2,4,6]
True
> all even [2,4,5]
False
> all (\ls -> length ls > 2) [[1,2,3], [4,5,6]]
True
What does all
do?
What is all
’s type?
all
checks if all elements of a list satisfy a predicate.
all :: (a -> Bool) -> [a] -> Bool
all pred xs = and (map pred xs)
> any even [2,4,6]
True
> any even [2,4,5]
True
> any (\ls -> length ls > 2) [[1,2], [3,4]]
False
What does any
do?
What is any
’s type?
any
checks if any elements of a list satisfy a predicate.
any :: (a -> Bool) -> [a] -> Bool
any pred xs = or (map pred xs)
> takeWhile even [2,4,6,3,4,5,6]
[2,4,6]
> takeWhile (\x -> x < 5) [1,3,5,7,2,4,6]
[1,3]
What does takeWhile
do?
What is takeWhile
’s type?
takeWhile
takes elements from a list while a predicate is true.
takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile pred [] = []
takeWhile pred (x:xs)
| pred x = x : takeWhile pred xs
| otherwise = []
> dropWhile even [2,4,6,3,4,5,6]
[3,4,5,6]
> dropWhile (\x -> x < 5) [1,3,5,7,2,4,6]
[5,7,2,4,6]
What does dropWhile
do?
What is dropWhile
’s type?
Try to implement dropWhile'
.
dropWhile' :: (a -> Bool) -> [a] -> [a]
Try to implement dropWhile'
.
dropWhile' :: (a -> Bool) -> [a] -> [a]
dropWhile' pred [] = []
dropWhile' pred (x:xs)
| pred x = dropWhile' pred xs
| otherwise = x:xs