functional programming - higher order functions

71
Functional Programming Higher-Order Functions H. Turgut Uyar 2013-2015

Upload: turgut-uyar

Post on 11-May-2015

642 views

Category:

Education


3 download

DESCRIPTION

Function order, functions as input parameters. Anonymous functions. Higher order list functions: filter, map, fold.

TRANSCRIPT

Page 1: Functional Programming - Higher Order Functions

Functional ProgrammingHigher-Order Functions

H. Turgut Uyar

2013-2015

Page 2: Functional Programming - Higher Order Functions

License

© 2013-2015 H. Turgut Uyar

You are free to:

Share – copy and redistribute the material in any medium or format

Adapt – remix, transform, and build upon the material

Under the following terms:

Attribution – You must give appropriate credit, provide a link to the license, andindicate if changes were made.

NonCommercial – You may not use the material for commercial purposes.

ShareAlike – If you remix, transform, or build upon the material, you mustdistribute your contributions under the same license as the original.

For more information:https://creativecommons.org/licenses/by-nc-sa/4.0/

Read the full license:

https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode

Page 3: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 4: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 5: Functional Programming - Higher Order Functions

First Class Values

first class values can be:

assigned

composed with other values

passed as parameters

returned as function results

in functional programming, functions are first class values

Page 6: Functional Programming - Higher Order Functions

First Class Values

first class values can be:

assigned

composed with other values

passed as parameters

returned as function results

in functional programming, functions are first class values

Page 7: Functional Programming - Higher Order Functions

Function Order

first order functions

only accept data as parameter, and

only return data as result

higher-order functions

take functions as parameters, or

return functions as result

Page 8: Functional Programming - Higher Order Functions

Function Order

first order functions

only accept data as parameter, and

only return data as result

higher-order functions

take functions as parameters, or

return functions as result

Page 9: Functional Programming - Higher Order Functions

First Order Function Examples

sum up the squares in a range

-- sqr :: Integer -> IntegersumSqr :: Integer -> Integer -> IntegersumSqr a b| a > b = 0| otherwise = sqr a + sumSqr (a + 1) b

sum up the factorials in a range

-- fac :: Integer -> IntegersumFac :: Integer -> Integer -> IntegersumFac a b| a > b = 0| otherwise = fac a + sumFac (a + 1) b

Page 10: Functional Programming - Higher Order Functions

First Order Function Examples

sum up the squares in a range

-- sqr :: Integer -> IntegersumSqr :: Integer -> Integer -> IntegersumSqr a b| a > b = 0| otherwise = sqr a + sumSqr (a + 1) b

sum up the factorials in a range

-- fac :: Integer -> IntegersumFac :: Integer -> Integer -> IntegersumFac a b| a > b = 0| otherwise = fac a + sumFac (a + 1) b

Page 11: Functional Programming - Higher Order Functions

Higher-Order Function Example

note the pattern

sumFun a b| a > b = 0| otherwise = fun a + sumFun (a + 1) b

send the function as parameter

sumF f a b| a > b = 0| otherwise = f a + sumF f (a + 1) b

sumSqr a b = sumF sqr a bsumFac a b = sumF fac a b

Page 12: Functional Programming - Higher Order Functions

Higher-Order Function Example

note the pattern

sumFun a b| a > b = 0| otherwise = fun a + sumFun (a + 1) b

send the function as parameter

sumF f a b| a > b = 0| otherwise = f a + sumF f (a + 1) b

sumSqr a b = sumF sqr a bsumFac a b = sumF fac a b

Page 13: Functional Programming - Higher Order Functions

Higher-Order Function Example

what is the type of sumF?

sumF :: (Integer -> Integer) -> Integer -> Integer-> Integer

Page 14: Functional Programming - Higher Order Functions

Higher-Order Function Example

Python

def sum_f(f, a, b):total = 0while a <= b:

total += f(a)a += 1

return total

def sqr(x):return x * x

def sum_sqr(a, b):return sum_f(sqr, a, b)

Page 15: Functional Programming - Higher Order Functions

Higher-Order Function Example

C

int sum_f(int (*f)(int), int a, int b){

int total = 0;while (a <= b){

total += f(a);a += 1;

}return total;

}

Page 16: Functional Programming - Higher Order Functions

Higher-Order Function Example

C

int sqr(int x){

return x * x;}

int sum_sqr(int a, int b){

return sum_f(sqr, a, b);}

Page 17: Functional Programming - Higher Order Functions

Higher-Order Function Example

Rock - Paper - Scissorsparameterize generateMatch regarding both strategies

type Strategy = [Move] -> Move

generateMatch :: Strategy -> Strategy -> Integer-> Match

generateMatch _ _ 0 = ([], [])generateMatch sA sB n =

step (generateMatch sA sB (n - 1))wherestep :: Match -> Matchstep (movesA, movesB) = (sA movesB : movesA,

sB movesA : movesB)

Page 18: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 19: Functional Programming - Higher Order Functions

Sorting

in C, qsort takes comparison function as parameter

typedef struct {int num, denom;

} rational;

rational items[] = {{3, 2}, {1, 3}, {2, 1}};qsort(items, 3, sizeof(rational), compare_rationals);

Page 20: Functional Programming - Higher Order Functions

Sorting

int compare_rationals(const void *r1, const void *r2){

int num1 = ((rational *) r1)->num;int denom1 = ((rational *) r1)->denom;int num2 = ((rational *) r2)->num;int denom2 = ((rational *) r2)->denom;

if (num1*denom2 > num2*denom1)return 1;

else if (num1*denom2 < num2*denom1)return -1;

elsereturn 0;

}

Page 21: Functional Programming - Higher Order Functions

Sorting

in Python, sorted takes key function as parameter

def second(p):return p[1]

def value(p):return p[0] / p[1]

pairs = [(3, 2), (1, 3), (2, 1)]

# sorted(pairs) ~> [(1, 3), (2, 1), (3, 2)]# sorted(pairs, key=second) ~> [(2, 1), (3, 2), (1, 3)]# sorted(pairs, key=value) ~> [(1, 3), (3, 2), (2, 1)]

Page 22: Functional Programming - Higher Order Functions

Sorting

parameterize qSort regarding comparison function

qSort :: (a -> a -> Bool) -> [a] -> [a]qSort precedes [] = []qSort precedes (x:xs) =

qSort precedes before ++ [x] ++ qSort precedes afterwherebefore = [a | a <- xs, a ‘precedes‘ x]after = [b | b <- xs, not (b ‘precedes‘ x)]

-- qSort (<=) [4, 5, 3] ~> [3, 4, 5]-- qSort (>) [4, 5, 3] ~> [5, 4, 3]-- qSort (<=) ["b", "a", "c"] ~> ["a", "b", "c"]

Page 23: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 24: Functional Programming - Higher Order Functions

Anonymous Functions

no need to name small functions that are not used anywhere else→ anonymous functions

\x1 x2 ... -> e

example

sumSqr :: Integer -> Integer -> IntegersumSqr a b = sumF (\x -> x * x) a b

Page 25: Functional Programming - Higher Order Functions

Anonymous Functions

no need to name small functions that are not used anywhere else→ anonymous functions

\x1 x2 ... -> e

example

sumSqr :: Integer -> Integer -> IntegersumSqr a b = sumF (\x -> x * x) a b

Page 26: Functional Programming - Higher Order Functions

Anonymous Functions

f x = e is the same as f = \x -> e

except that anonymous functions can’t be recursive

Page 27: Functional Programming - Higher Order Functions

Anonymous Functions

Python

lambda x1, x2, ...: e

examples

def sum_sqr(a, b):sum_func(lambda x: x * x, a, b)

sorted(pairs, key=lambda p: p[0] / p[1])

Page 28: Functional Programming - Higher Order Functions

Anonymous Functions

Python

lambda x1, x2, ...: e

examples

def sum_sqr(a, b):sum_func(lambda x: x * x, a, b)

sorted(pairs, key=lambda p: p[0] / p[1])

Page 29: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 30: Functional Programming - Higher Order Functions

Fixed Points

x is a fixed point of f:f(x) = x

repeatedly apply f until value doesn’t change:x→ f(x)→ f(f(x))→ f(f(f(x)))→ . . .

Page 31: Functional Programming - Higher Order Functions

Fixed Points

find fixed point

fixedPoint :: (Float -> Float) -> Float -> FloatfixedPoint f firstGuess = fpIter firstGuesswherefpIter :: Float -> FloatfpIter guess| isCloseEnough guess next = next| otherwise = fpIter nextwherenext = f guess

isCloseEnough :: Float -> Float -> BoolisCloseEnough x y = (abs (x-y) / x) < 0.001

Page 32: Functional Programming - Higher Order Functions

Square Roots

use fixed points to compute square roots

y =√

x⇒ y ∗ y = x⇒ y = x/y

fixed point of the function f(y) = x/y

sqrt :: Float -> Floatsqrt x = fixedPoint (\y -> x / y) 1.0

doesn’t converge (try with x = 2)

average successive values (average damping)

sqrt x = fixedPoint (\y -> (y + x/y) / 2.0) 1.0

Page 33: Functional Programming - Higher Order Functions

Square Roots

use fixed points to compute square roots

y =√

x⇒ y ∗ y = x⇒ y = x/y

fixed point of the function f(y) = x/y

sqrt :: Float -> Floatsqrt x = fixedPoint (\y -> x / y) 1.0

doesn’t converge (try with x = 2)

average successive values (average damping)

sqrt x = fixedPoint (\y -> (y + x/y) / 2.0) 1.0

Page 34: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 35: Functional Programming - Higher Order Functions

Filter

select all elements with a given property

all odd elements of a list

-- allOdds [4, 1, 3, 2] ~> [1, 3]allOdds :: [Integer] -> [Integer]

-- primitive recursiveallOdds [] = []allOdds (x:xs)| odd x = x : allOdds xs| otherwise = allOdds xs

-- list comprehensionallOdds xs = [x | x <- xs, odd x]

Page 36: Functional Programming - Higher Order Functions

Filter

filter: select elements that satisfy a predicate

-- primitive recursivefilter f [] = []filter f (x:xs)| f x = x : filter f xs| otherwise = filter f xs

-- list comprehensionfilter f xs = [x | x <- xs, f x]

what is the type of filter?filter :: (a -> Bool) -> [a] -> [a]

Page 37: Functional Programming - Higher Order Functions

Filter

filter: select elements that satisfy a predicate

-- primitive recursivefilter f [] = []filter f (x:xs)| f x = x : filter f xs| otherwise = filter f xs

-- list comprehensionfilter f xs = [x | x <- xs, f x]

what is the type of filter?filter :: (a -> Bool) -> [a] -> [a]

Page 38: Functional Programming - Higher Order Functions

Filter Example

all odd elements of a list

allOdds :: [Integer] -> [Integer]allOdds xs = filter odd xs

Python

def odd(n):return n%2 == 1

filter(odd, [4, 1, 3, 2])

Page 39: Functional Programming - Higher Order Functions

Filter Example

how many elements in a list are above a threshold?

howManyAbove :: Float -> [Float] -> InthowManyAbove t xs = length (filter (\x -> x > t) xs)

Page 40: Functional Programming - Higher Order Functions

Splitting Lists

take elements from the front of a list while a predicate is truetakeWhile even [8, 2, 4, 5, 6] ~> [8, 2, 4]

takeWhile :: (a -> Bool) -> [a] -> [a]takeWhile f [] = []takeWhile f (x:xs)| f x = x : takeWhile f xs| otherwise = []

exercise: drop elements from the front of a listwhile a predicate is truedropWhile even [8, 2, 4, 5, 6] ~> [5, 6]

Page 41: Functional Programming - Higher Order Functions

Splitting Lists

take elements from the front of a list while a predicate is truetakeWhile even [8, 2, 4, 5, 6] ~> [8, 2, 4]

takeWhile :: (a -> Bool) -> [a] -> [a]takeWhile f [] = []takeWhile f (x:xs)| f x = x : takeWhile f xs| otherwise = []

exercise: drop elements from the front of a listwhile a predicate is truedropWhile even [8, 2, 4, 5, 6] ~> [5, 6]

Page 42: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 43: Functional Programming - Higher Order Functions

Map

transform all elements of a list

example: floors of all elements of a list

-- floorAll [5.7, 9.0, 2.3] ~> [5, 9, 2]floorAll :: [Float] -> [Integer]

-- primitive recursivefloorAll [] = []floorAll (x:xs) = floor x : floorAll xs

-- list comprehensionfloorAll xs = [floor x | x <- xs]

Page 44: Functional Programming - Higher Order Functions

Map

map: apply a function to all elements of a list

-- primitive recursivemap f [] = []map f (x:xs) = f x : map f xs

-- list comprehensionmap f xs = [f x | x <- xs]

what is the type?map :: (a -> b) -> [a] -> [b]

Page 45: Functional Programming - Higher Order Functions

Map

map: apply a function to all elements of a list

-- primitive recursivemap f [] = []map f (x:xs) = f x : map f xs

-- list comprehensionmap f xs = [f x | x <- xs]

what is the type?map :: (a -> b) -> [a] -> [b]

Page 46: Functional Programming - Higher Order Functions

Map Example

floors of all elements of a list

floorAll :: [Float] -> [Integer]floorAll xs = map floor xs

Python

import math

map(math.floor, [5.7, 9.0, 2.3])

Page 47: Functional Programming - Higher Order Functions

Map Examples

make a list of n copies of an item

replicate :: Int -> a -> [a]replicate n i = map (\_ -> i) [1 .. n]

zip two lists over a function

zipWith (+) [1, 2] [10, 12] ~> [11, 14]zipWith replicate [3, 2] [’a’, ’b’] ~> ["aaa", "bb"]

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]zipWith f xs ys = map (\(x, y) -> f x y) (zip xs ys)

Page 48: Functional Programming - Higher Order Functions

Map Examples

make a list of n copies of an item

replicate :: Int -> a -> [a]replicate n i = map (\_ -> i) [1 .. n]

zip two lists over a function

zipWith (+) [1, 2] [10, 12] ~> [11, 14]zipWith replicate [3, 2] [’a’, ’b’] ~> ["aaa", "bb"]

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]zipWith f xs ys = map (\(x, y) -> f x y) (zip xs ys)

Page 49: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 50: Functional Programming - Higher Order Functions

Fold

reduce the elements of a list to a single value

sum all elements of a non-empty list

-- sum [2, 8, 5] ~> 15sum :: [Integer] -> Integersum [x] = xsum (x:xs) = x + sum xs

Page 51: Functional Programming - Higher Order Functions

Fold

foldr1: reduce a non-empty list to a value over a function

foldr1 f [x] = xfoldr1 f (x:xs) = x ‘f‘ (foldr1 f xs)

-- OR:foldr1 f [x] = xfoldr1 f (x:xs) = f x (foldr1 f xs)

what is the type of foldr1?foldr1 :: (a -> a -> a) -> [a] -> a

Page 52: Functional Programming - Higher Order Functions

Fold

foldr1: reduce a non-empty list to a value over a function

foldr1 f [x] = xfoldr1 f (x:xs) = x ‘f‘ (foldr1 f xs)

-- OR:foldr1 f [x] = xfoldr1 f (x:xs) = f x (foldr1 f xs)

what is the type of foldr1?foldr1 :: (a -> a -> a) -> [a] -> a

Page 53: Functional Programming - Higher Order Functions

Fold Expansion

foldr1 f [e1, e2, ..., ej, ek]= e1 ‘f‘ (e2 ‘f‘ (... (ej ‘f‘ ek)...)= e1 ‘f‘ (foldr1 f [e2, ..., ej, ek])= f e1 (foldr1 f [e2, ..., ej, ek])

Page 54: Functional Programming - Higher Order Functions

Fold

sum all elements of a list

sum :: [Integer] -> Integersum xs = foldr1 (+) xs

Python

import functoolsimport operator

def sum(xs):return functools.reduce(operator.add, xs)

Page 55: Functional Programming - Higher Order Functions

Fold with Initial Value

foldr1 doesn’t work on empty lists

add a parameter as initial value for empty list: foldr

foldr f s [e1, e2, ..., ej, ek]= e1 ‘f‘ (e2 ‘f‘ (... (ej ‘f‘ (ek ‘f‘ s))...)= e1 ‘f‘ (foldr f s [e2, ..., ej, ek])= f e1 (foldr f s [e2, ..., ej, ek])

Page 56: Functional Programming - Higher Order Functions

Fold with Initial Value

foldr f s [] = sfoldr f s (x:xs) = f x (foldr f s xs)

what is the type of foldr?foldr :: (a -> b -> b) -> b -> [a] -> b

Page 57: Functional Programming - Higher Order Functions

Fold with Initial Value

foldr f s [] = sfoldr f s (x:xs) = f x (foldr f s xs)

what is the type of foldr?foldr :: (a -> b -> b) -> b -> [a] -> b

Page 58: Functional Programming - Higher Order Functions

Fold with Initial Value

sum all elements of a list

sum :: [Integer] -> Integersum xs = foldr (+) 0 xs

Python

import functoolsimport operator

def sum(xs):return functools.reduce(operator.add, xs, 0)

Page 59: Functional Programming - Higher Order Functions

Fold Examples

product :: [Integer] -> Integerproduct xs = foldr (*) 1 xs

fac :: [Integer] -> Integerfac n = foldr (*) 1 [1 .. n]

and :: [Bool] -> Booland xs = foldr (&&) True xs

concat :: [[a]] -> [a]concat xs = foldr (++) [] xs

maxList :: [Integer] -> IntegermaxList xs = foldr1 max xs

Page 60: Functional Programming - Higher Order Functions

Fold Example

how many elements in a list are above a threshold?

howManyAbove :: Float -> [Float] -> IntegerhowManyAbove t xs =

foldr (\x n -> if x > t then n + 1 else n) 0 xs

Page 61: Functional Programming - Higher Order Functions

Fold Example

insertion sort

ins :: Integer -> [Integer] -> [Integer]ins i [] = [i]ins i (x:xs)| i <= x = i : x : xs| otherwise = x : ins i xs

iSort :: [Integer] -> [Integer]iSort [] = []iSort (x:xs) = ins x (iSort xs)

-- equivalent to:iSort :: [Integer] -> [Integer]iSort (x:xs) = foldr ins [] xs

Page 62: Functional Programming - Higher Order Functions

Fold Left

foldl f s [e1, e2, ..., ej, ek]= (...((s ‘f‘ e1) ‘f‘ e2) ‘f‘ ... ej) ‘f‘ ek= foldl f (s ‘f‘ e1) [e2, ..., ej, ek]= foldl f (f s e1) [e2, ..., ej, ek]

foldl f s [] = sfoldl f s (x:xs) = foldl f (f s x) xs

what is the type of foldl?foldl :: (a -> b -> a) -> a -> [b] -> a

Page 63: Functional Programming - Higher Order Functions

Fold Left

foldl f s [e1, e2, ..., ej, ek]= (...((s ‘f‘ e1) ‘f‘ e2) ‘f‘ ... ej) ‘f‘ ek= foldl f (s ‘f‘ e1) [e2, ..., ej, ek]= foldl f (f s e1) [e2, ..., ej, ek]

foldl f s [] = sfoldl f s (x:xs) = foldl f (f s x) xs

what is the type of foldl?foldl :: (a -> b -> a) -> a -> [b] -> a

Page 64: Functional Programming - Higher Order Functions

Fold Left

foldl f s [e1, e2, ..., ej, ek]= (...((s ‘f‘ e1) ‘f‘ e2) ‘f‘ ... ej) ‘f‘ ek= foldl f (s ‘f‘ e1) [e2, ..., ej, ek]= foldl f (f s e1) [e2, ..., ej, ek]

foldl f s [] = sfoldl f s (x:xs) = foldl f (f s x) xs

what is the type of foldl?foldl :: (a -> b -> a) -> a -> [b] -> a

Page 65: Functional Programming - Higher Order Functions

Fold Right - Fold Left

results not the same if function is not commutative

example

foldr (*) 1 [1 .. 7] ~> 5040foldl (*) 1 [1 .. 7] ~> 5040

foldr (/) 1.0 [1.0, 2.0, 3.0] ~> 1.5foldl (/) 1.0 [1.0, 2.0, 3.0] ~> 0.1666666

Page 66: Functional Programming - Higher Order Functions

Topics

1 Higher-Order FunctionsFunction OrderExample: SortingAnonymous FunctionsExample: Fixed Points

2 List FunctionsFilterMapFoldExample: Edit Distance

Page 67: Functional Programming - Higher Order Functions

Edit Distance

transform a source string into a destination stringoperations: copy, insert, delete, change

use the minimum number of operations

data Edit = Copy | Insert Char | Delete | Change Charderiving (Eq, Show)

Page 68: Functional Programming - Higher Order Functions

Edit Distance

transform :: String -> String -> [Edit]transform [] [] = []transform xs [] = map (\_ -> Delete) xstransform [] ys = map Insert ystransform xs@(x’:xs’) ys@(y’:ys’)| x’ == y’ = Copy : transform xs’ ys’| otherwise = best [Insert y’ : transform xs ys’,

Delete : transform xs’ ys,Change y’ : transform xs’ ys’]

Page 69: Functional Programming - Higher Order Functions

Edit Distance

find best path

best :: [[Edit]] -> [Edit]best [x] = xbest (x:xs)| cost x <= cost b = x| otherwise = bwhereb = best xs

cost :: [Edit] -> Intcost xs = length (filter (\x -> x /= Copy) xs)

exercise: implement best using fold

Page 70: Functional Programming - Higher Order Functions

Edit Distance

find best path

best :: [[Edit]] -> [Edit]best [x] = xbest (x:xs)| cost x <= cost b = x| otherwise = bwhereb = best xs

cost :: [Edit] -> Intcost xs = length (filter (\x -> x /= Copy) xs)

exercise: implement best using fold

Page 71: Functional Programming - Higher Order Functions

References

Required Reading: ThompsonChapter 10: Generalization: patterns of computation