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)8What 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