Joseph Haugh
University of New Mexico
What is a better name for this function?
foo f xs = foldr (\x rest -> f x : rest) [] xs
map
What type does this expression have?
map (foldr (:) []) ::
map (foldr (:) []) :: [[a]] -> [[a]]
foldr :: (a -> b -> b) -> b -> [a] -> b
(:) :: a -> [a] -> [a]
a = a, b = [a]
foldr (:) :: [a] -> [a] -> [a]
foldr (:) [] :: [a] -> [a]
map :: ( a -> b) -> [a] -> [b]
a = [a], b = [a]
map (foldr (:) []) :: [[a]] -> [[a]]
What does this expression evaluate to?
add1 x = x + 1
div2 x = x `div` 2
div2 (add1 3) ===
add1 x = x + 1
div2 x = x `div` 2
div2 (add1 3) === 2
So far we have seen many higher order functions:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
So far we have seen many higher order functions:
filter :: (a -> Bool) -> [a] -> [a]
filter p [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
So far we have seen many higher order functions:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
So far we have seen many higher order functions:
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl f acc [] = acc
foldl f acc (x:xs) = foldl f (acc `f` x) xs
But we haven’t seen a function that both takes a function as an argument and returns a function as a result.
Why might such a function be useful?
Recall from the review:
add1 x = x + 1
div2 x = x `div` 2
div2 (add1 3)
Could we write a function which generalizes this pattern?
add1 x = x + 1
div2 x = x `div` 2
div2 (add1 3)
What type would such a function have?
It would need to take in two functions and return a function.
The inner function, add1, must return the same type as the input to the outer function, div2.
Then the whole function would take the input type of the inner function and return the output type of the outer function.
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
Notice that g is applied first, thus, the order goes from right to left.
Now we could rewrite the review question as:
add1 x = x + 1
div2 x = x `div` 2
(div2 . add1) 3
We can simplify nesting with compose:
odd n = not (even n)
twice f x = f (f x)
sumSqrEven ns = sum (map (^2) (filter even ns))
We can simplify nesting with compose:
odd = not . even
twice f x = f (f x)
sumSqrEven ns = sum (map (^2) (filter even ns))
We can simplify nesting with compose:
odd = not . even
twice f = f . f
sumSqrEven ns = sum (map (^2) (filter even ns))
We can simplify nesting with compose:
odd = not . even
twice f = f . f
sumSqrEven = sum . map (^2) . filter even
What happened to the parameters?
odd = not . even
twice f = f . f
sumSqrEven = sum . map (^2) . filter even
This conversion is called eta reduction.
You have probably seen HLS yell at you for it many times.
So what does it mean?
In general eta reduction is the turning an expression of the form:
\x -> f x
Into
f
For example:
add1All :: [Int] -> [Int]
add1All xs = map (+1) xs
Can be rewritten as:
add1All :: [Int] -> [Int]
add1All = map (+1)
You might be asking yourself well doesn’t that mess up the type of the function?
Take a look at the above example again:
add1All :: [Int] -> [Int]
add1All xs = map (+1) xs
What is the type of add1All xs? [Int]
What is the type of map (+1) xs? [Int]
add1All :: [Int] -> [Int]
add1All = map (+1)
What is the type of add1All? [Int] -> [Int]
What is the type of map (+1)? [Int] -> [Int]
The types still match!
Recall identity elements of functions:
x + 0 = x
0 + x = x
x * 1 = x
1 * x = x
Does (.) have an identity element?
Attempt to define a function, foo, that when given to (.) will exhibit the following behavior:
foo . g = g
f . foo = f
Attempt to define a function, foo, that when given to (.) will exhibit the following behavior:
foo . g = g
f . foo = f
foo :: a -> a
foo x = x
((+1) . foo) 3 === 4
(foo . (+1)) 3 === 4
This is the builtin function id.
Define a function, composeList, which takes in a list of functions, a -> a, and returns a single function, a -> a, which composes the functions in the list from right to left. Define it with explicit recursion:
composeList :: [a -> a] -> a -> a
Define a function, composeList, which takes in a list of functions, a -> a, and returns a single function, a -> a, which composes the functions in the list from right to left. Define it with explicit recursion:
composeList :: [a -> a] -> a -> a
composeList [] = \x -> x
composeList (f:fs) = f . composeList fs
Now define it with foldr:
composeList :: [a -> a] -> a -> a
Now define it with foldr:
composeList :: [a -> a] -> a -> a
composeList = foldr (.) id
Define a function, iterateN, which takes in a function, f a -> a, and an integer, n, and composes the function with itself n times. Define it with explicit recursion:
iterateN :: (a -> a) -> Int -> a -> a
Define a function, iterateN, which takes in a function, f a -> a, and an integer, n, and composes the function with itself n times. Define it with explicit recursion:
iterateN :: (a -> a) -> Int -> a -> a
iterateN f 0 = id
iterateN f n = f . iterateN f (n-1)
Now define it with foldr:
iterateN :: (a -> a) -> Int -> a -> a
Now define it with foldr:
iterateN :: (a -> a) -> Int -> a -> a
iterateN f n = foldr (\x rest -> f . rest) id [0..n]
Heron’s method is an iterative way to approximate the square root of a number. It is given by the following equation:
$x_{n+1} = \frac{1}{2} \left( x_n + \frac{S}{x_n} \right)$
Where x0 is the initial guess and xn + 1 is the next guess.
How can we write this in Haskell?
First just translate this formula:
$x_{n+1} = \frac{1}{2} \left( x_n + \frac{S}{x_n} \right)$
Into Haskell, where the first argument is the number you are trying to find the square root of, S, and the second argument is the current guess, xn.
heron :: Double -> Double -> Double
First just translate this formula:
$x_{n+1} = \frac{1}{2} \left( x_n + \frac{S}{x_n} \right)$
Into Haskell, where the first argument is the number you are trying to find the square root of, S, and the second argument is the current guess, xn.
heron :: Double -> Double -> Double
heron s x = (x + s / x) / 2
Now how can we use this to iteratively improve our guess?
Hint: Use iterateN.
sqrt' :: Double -> Double
Now how can we use this to iteratively improve our guess?
Hint: Use iterateN.
sqrt' :: Double -> Double
sqrt' s = iterateN (heron s) 10 s
Can we eta reduce this?
No! Why?
Because s appears in a place other than the last argument.
\x -> f x
f {as long as x is not used in f, in other words
f has no free occurrences of x}