Programming Languages (TC-2006)
Transcript of Programming Languages (TC-2006)
Programming Languages(TC-2006)
Higher-order functions and lazy evaluation in Haskell
Jose Carlos Ortiz [email protected]
Contents
1 Lambda functions
2 Some useful higher-order functions
3 ‘Monads’
4 Lazy evaluation
2 / 23
Lambda functions
Lambda functions have no name.
Character ’\’ is used before the parameters to define a lambda function.
For example:
(\x -> x + 1) 10 ⇒ 11
(\x y -> x * y) 3 4 ⇒ 12
(\x -> x - 10) ((\x y -> x * y) 3 4) ⇒ 2
(\x -> fst x * snd x) (3, 5) ⇒ 15
3 / 23
Lambda functions
Lambda functions have no name.
Character ’\’ is used before the parameters to define a lambda function.
For example:
(\x -> x + 1) 10 ⇒ 11
(\x y -> x * y) 3 4 ⇒ 12
(\x -> x - 10) ((\x y -> x * y) 3 4) ⇒ 2
(\x -> fst x * snd x) (3, 5) ⇒ 15
3 / 23
Lambda functions
Lambda functions have no name.
Character ’\’ is used before the parameters to define a lambda function.
For example:
(\x -> x + 1) 10 ⇒ 11
(\x y -> x * y) 3 4 ⇒ 12
(\x -> x - 10) ((\x y -> x * y) 3 4) ⇒ 2
(\x -> fst x * snd x) (3, 5) ⇒ 15
3 / 23
Lambda functions
Lambda functions have no name.
Character ’\’ is used before the parameters to define a lambda function.
For example:
(\x -> x + 1) 10 ⇒ 11
(\x y -> x * y) 3 4 ⇒ 12
(\x -> x - 10) ((\x y -> x * y) 3 4) ⇒ 2
(\x -> fst x * snd x) (3, 5) ⇒ 15
3 / 23
Lambda functions
Lambda functions have no name.
Character ’\’ is used before the parameters to define a lambda function.
For example:
(\x -> x + 1) 10 ⇒ 11
(\x y -> x * y) 3 4 ⇒ 12
(\x -> x - 10) ((\x y -> x * y) 3 4) ⇒ 2
(\x -> fst x * snd x) (3, 5) ⇒ 15
3 / 23
Higher-order functions
Higher-order functions are functions that can be applied to other functions:
map.
all and any.
filter.
foldl and foldl1.
foldr and foldr1.
compose.
4 / 23
Applying a function to each element in a list: map
map function list
Function map applies a function to all the elements in a list and returnsthe result as a list.
For example:
map sqrt [4, 9, 16, 25] ⇒ [2.0, 3.0, 4.0, 5.0]
map (\x -> x * x) [1, 2, 3, 4, 5] ⇒ [1, 4, 9, 16, 25]
5 / 23
Applying a function to each element in a list: map
map function list
Function map applies a function to all the elements in a list and returnsthe result as a list.
For example:
map sqrt [4, 9, 16, 25] ⇒ [2.0, 3.0, 4.0, 5.0]
map (\x -> x * x) [1, 2, 3, 4, 5] ⇒ [1, 4, 9, 16, 25]
5 / 23
Applying a function to each element in a list: map
map function list
Function map applies a function to all the elements in a list and returnsthe result as a list.
For example:
map sqrt [4, 9, 16, 25] ⇒ [2.0, 3.0, 4.0, 5.0]
map (\x -> x * x) [1, 2, 3, 4, 5] ⇒ [1, 4, 9, 16, 25]
5 / 23
map in action: dot product
dotProduct :: [Int] -> [Int] -> IntdotProduct v w = sum (map (\(x, y) -> x * y) (zip v w))
> dotProduct [1, 2, 3] [10, 20, 30]140
6 / 23
map in action: dot product
dotProduct :: [Int] -> [Int] -> IntdotProduct v w = sum (map (\(x, y) -> x * y) (zip v w))
> dotProduct [1, 2, 3] [10, 20, 30]140
6 / 23
all and any
Function all applies a predicate to all the elements in a list and checksif all the elements fulfil this predicate.
all even [1, 2, 3, 4, 5] ⇒ False
Function all applies a predicate to all the elements in a list and checksif at least one of the elements fulfils this predicate.
any even [1, 2, 3, 4, 5] ⇒ True
7 / 23
all and any
Function all applies a predicate to all the elements in a list and checksif all the elements fulfil this predicate.
all even [1, 2, 3, 4, 5] ⇒ False
Function all applies a predicate to all the elements in a list and checksif at least one of the elements fulfils this predicate.
any even [1, 2, 3, 4, 5] ⇒ True
7 / 23
all and any
Function all applies a predicate to all the elements in a list and checksif all the elements fulfil this predicate.
all even [1, 2, 3, 4, 5] ⇒ False
Function all applies a predicate to all the elements in a list and checksif at least one of the elements fulfils this predicate.
any even [1, 2, 3, 4, 5] ⇒ True
7 / 23
all and any
Function all applies a predicate to all the elements in a list and checksif all the elements fulfil this predicate.
all even [1, 2, 3, 4, 5] ⇒ False
Function all applies a predicate to all the elements in a list and checksif at least one of the elements fulfils this predicate.
any even [1, 2, 3, 4, 5] ⇒ True
7 / 23
Filtering a list: filter
filter predicate list
Function filter produces a list with all the elements in a list thatfulfil a given predicate.
For example:
filter even [1, 2, 3, 4, 5] ⇒ [2, 4]
filter odd [1, 2, 3, 4, 5] ⇒ [1, 3, 5]
filter (> 3) [1, 2, 3, 4, 5] ⇒ [4, 5]
filter (\x -> odd x && x < 10) [3, 6, 9, 12, 15] ⇒ [3, 9]
8 / 23
Filtering a list: filter
filter predicate list
Function filter produces a list with all the elements in a list thatfulfil a given predicate.
For example:
filter even [1, 2, 3, 4, 5] ⇒ [2, 4]
filter odd [1, 2, 3, 4, 5] ⇒ [1, 3, 5]
filter (> 3) [1, 2, 3, 4, 5] ⇒ [4, 5]
filter (\x -> odd x && x < 10) [3, 6, 9, 12, 15] ⇒ [3, 9]
8 / 23
Filtering a list: filter
filter predicate list
Function filter produces a list with all the elements in a list thatfulfil a given predicate.
For example:
filter even [1, 2, 3, 4, 5] ⇒ [2, 4]
filter odd [1, 2, 3, 4, 5] ⇒ [1, 3, 5]
filter (> 3) [1, 2, 3, 4, 5] ⇒ [4, 5]
filter (\x -> odd x && x < 10) [3, 6, 9, 12, 15] ⇒ [3, 9]
8 / 23
Filtering a list: filter
filter predicate list
Function filter produces a list with all the elements in a list thatfulfil a given predicate.
For example:
filter even [1, 2, 3, 4, 5] ⇒ [2, 4]
filter odd [1, 2, 3, 4, 5] ⇒ [1, 3, 5]
filter (> 3) [1, 2, 3, 4, 5] ⇒ [4, 5]
filter (\x -> odd x && x < 10) [3, 6, 9, 12, 15] ⇒ [3, 9]
8 / 23
Filtering a list: filter
filter predicate list
Function filter produces a list with all the elements in a list thatfulfil a given predicate.
For example:
filter even [1, 2, 3, 4, 5] ⇒ [2, 4]
filter odd [1, 2, 3, 4, 5] ⇒ [1, 3, 5]
filter (> 3) [1, 2, 3, 4, 5] ⇒ [4, 5]
filter (\x -> odd x && x < 10) [3, 6, 9, 12, 15] ⇒ [3, 9]
8 / 23
Sorting a list: quicksort (using let)
quicksort :: [Int] -> [Int]quicksort [] = []quicksort (first:rest) = let
leftList = filter (< first) restrightList = filter (>= first) restin(quicksort leftList) ++ [first] ++ (quicksort rightList)
> quicksort [5, -2, 9, 8, 10, 3, 14][-2,3,5,8,9,10,14]
9 / 23
Sorting a list: quicksort (using let)
quicksort :: [Int] -> [Int]quicksort [] = []quicksort (first:rest) = let
leftList = filter (< first) restrightList = filter (>= first) restin(quicksort leftList) ++ [first] ++ (quicksort rightList)
> quicksort [5, -2, 9, 8, 10, 3, 14][-2,3,5,8,9,10,14]
9 / 23
Folding a list: foldl and foldl1
Function foldl reduces a list by applying a binary operator (firstargument) from left to right and using the second argument as initialvalue for the calculation.
foldl (-) 1 [2, 3, 4, 5] ⇒ -13
foldl (\x y -> x - y) 1 [2, 3, 4, 5] ⇒ -13
Function foldl1 does the same than foldl does but without initialvalue.
foldl1 (-) [1, 2, 3, 4, 5] ⇒ -13
10 / 23
Folding a list: foldr and foldr1
Function foldr reduces a list by applying a binary operator (firstargument) from right to left and using the second argument as initialvalue for the calculation.
foldr (-) 1 [2, 3, 4, 5] ⇒ -1
Function foldr1 does the same than foldr does but without initialvalue.
foldr1 (-) [2, 3, 4, 5, 1] ⇒ -1
foldr1 (-) [1, 2, 3, 4, 5] ⇒ 3
11 / 23
“Chaining” functions: compose
Function compose takes two functions and ‘chains’ them.
Using (f . g . h) x is equivalent to f (g (h x)).
For example:
(sqrt . sum) [4, 9, 16, 25] ⇒ 7.3484
(sum . map sqrt) [4, 9, 16, 25] ⇒ 14
(foldl1 (*) . map abs) [1, -2, 3] ⇒ 6
12 / 23
“Chaining” functions: compose
Function compose takes two functions and ‘chains’ them.
Using (f . g . h) x is equivalent to f (g (h x)).
For example:
(sqrt . sum) [4, 9, 16, 25] ⇒ 7.3484
(sum . map sqrt) [4, 9, 16, 25] ⇒ 14
(foldl1 (*) . map abs) [1, -2, 3] ⇒ 6
12 / 23
“Chaining” functions: compose
Function compose takes two functions and ‘chains’ them.
Using (f . g . h) x is equivalent to f (g (h x)).
For example:
(sqrt . sum) [4, 9, 16, 25] ⇒ 7.3484
(sum . map sqrt) [4, 9, 16, 25] ⇒ 14
(foldl1 (*) . map abs) [1, -2, 3] ⇒ 6
12 / 23
“Chaining” functions: compose
Function compose takes two functions and ‘chains’ them.
Using (f . g . h) x is equivalent to f (g (h x)).
For example:
(sqrt . sum) [4, 9, 16, 25] ⇒ 7.3484
(sum . map sqrt) [4, 9, 16, 25] ⇒ 14
(foldl1 (*) . map abs) [1, -2, 3] ⇒ 6
12 / 23
The factorial
factorial :: Int -> Intfactorial n
| n == 0 = 1| n > 0 = n * factorial (n - 1)
> factorial 5120
14 / 23
The factorial
factorial :: Int -> Intfactorial n
| n == 0 = 1| n > 0 = n * factorial (n - 1)
> factorial 5120
14 / 23
Selecting even elements from a list
getEven :: [Int] -> [Int]getEven [] = []getEven (first:rest)
| even first = first : getEven rest| otherwise = getEven rest
> getEven [4, 10, 3, 1, 8, 9][4,10,8]
15 / 23
Selecting even elements from a list
getEven :: [Int] -> [Int]getEven [] = []getEven (first:rest)
| even first = first : getEven rest| otherwise = getEven rest
> getEven [4, 10, 3, 1, 8, 9][4,10,8]
15 / 23
Generators
[xi | xi <- x, xi > 0] means: “create a list with every xi ∈ xwhere xi > 0”.
xi <- x is usually referred to as a generator.
positives :: [Int] -> [Int]positives x = [xi | xi <- x, xi > 0]
> positives [2, 3, -1, 10, -6][2,3,10]
16 / 23
Generators
[xi | xi <- x, xi > 0] means: “create a list with every xi ∈ xwhere xi > 0”.
xi <- x is usually referred to as a generator.
positives :: [Int] -> [Int]positives x = [xi | xi <- x, xi > 0]
> positives [2, 3, -1, 10, -6][2,3,10]
16 / 23
Generators
[xi | xi <- x, xi > 0] means: “create a list with every xi ∈ xwhere xi > 0”.
xi <- x is usually referred to as a generator.
positives :: [Int] -> [Int]positives x = [xi | xi <- x, xi > 0]
> positives [2, 3, -1, 10, -6][2,3,10]
16 / 23
Cartesian product
cartesian :: [t] -> [t] -> [(t, t)]cartesian x y = [(xi, yi) | xi <- x, yi <- y]
> cartesian [1, 2] [3, 4][(1,3),(1,4),(2,3),(2,4)]
17 / 23
Cartesian product
cartesian :: [t] -> [t] -> [(t, t)]cartesian x y = [(xi, yi) | xi <- x, yi <- y]
> cartesian [1, 2] [3, 4][(1,3),(1,4),(2,3),(2,4)]
17 / 23
Cartesian product (with an additional constraint)
cartesianSum :: [Int] -> [Int] -> [(Int, Int)]cartesianSum x y = [(xi, yi) | xi <- x, yi <- y, (xi + yi) >= 5]
> cartesianSum [1, 2, 3] [1, 2, 3][(2,3),(3,2),(3,3)]
18 / 23
Cartesian product (with an additional constraint)
cartesianSum :: [Int] -> [Int] -> [(Int, Int)]cartesianSum x y = [(xi, yi) | xi <- x, yi <- y, (xi + yi) >= 5]
> cartesianSum [1, 2, 3] [1, 2, 3][(2,3),(3,2),(3,3)]
18 / 23
Counting the occurrences of a number
occurrences :: Int -> [Int] -> Intoccurrences n x = length [xi | xi <- x, n == xi]
> occurrences 1 [1, 2, 3, 4, 1, 1, 5, 6]3
19 / 23
Counting the occurrences of a number
occurrences :: Int -> [Int] -> Intoccurrences n x = length [xi | xi <- x, n == xi]
> occurrences 1 [1, 2, 3, 4, 1, 1, 5, 6]3
19 / 23
Sorting a list: quicksort (using where)
qSort :: [Int] -> [Int]qSort [] = []qSort (first:rest) =
(qSort leftList) ++ [first] ++ (qSort rightList)where
leftList = [lefti | lefti <- rest, lefti < first]rightList = [righti | righti <- rest, righti >= first]
> qSort [5, -2, 9, 8, 10, 3, 14][-2,3,5,8,9,10,14]
20 / 23
Sorting a list: quicksort (using where)
qSort :: [Int] -> [Int]qSort [] = []qSort (first:rest) =
(qSort leftList) ++ [first] ++ (qSort rightList)where
leftList = [lefti | lefti <- rest, lefti < first]rightList = [righti | righti <- rest, righti >= first]
> qSort [5, -2, 9, 8, 10, 3, 14][-2,3,5,8,9,10,14]
20 / 23
‘Infinite’ data structures
ones :: [Int]ones = 1:ones
> take 5 ones[1,1,1,1,1]
numbersFrom :: Int -> [Int]numbersFrom n = n:numbersFrom (n + 1)
> take 3 (numbersFrom 1000)[1000,1001,1002]
21 / 23
‘Infinite’ data structures
ones :: [Int]ones = 1:ones
> take 5 ones[1,1,1,1,1]
numbersFrom :: Int -> [Int]numbersFrom n = n:numbersFrom (n + 1)
> take 3 (numbersFrom 1000)[1000,1001,1002]
21 / 23
‘Infinite’ data structures
ones :: [Int]ones = 1:ones
> take 5 ones[1,1,1,1,1]
numbersFrom :: Int -> [Int]numbersFrom n = n:numbersFrom (n + 1)
> take 3 (numbersFrom 1000)[1000,1001,1002]
21 / 23
‘Infinite’ data structures
ones :: [Int]ones = 1:ones
> take 5 ones[1,1,1,1,1]
numbersFrom :: Int -> [Int]numbersFrom n = n:numbersFrom (n + 1)
> take 3 (numbersFrom 1000)[1000,1001,1002]
21 / 23
‘Infinite’ data structures
factorialInf :: Int -> IntfactorialInf n = product (take n [1..])
> factorialInf 5120
22 / 23
‘Infinite’ data structures
factorialInf :: Int -> IntfactorialInf n = product (take n [1..])
> factorialInf 5120
22 / 23
Lazy evaluation
Lazy evaluation evaluates expressions only when they are needed!
Once it has been evaluated, the result is saved for further computation,or discarded if it is not needed in any other running code.
Pros: only the minimal amount of computation is performed duringprogram execution.Cons: all the suspended expressions that have not yet been evaluatedmust be saved in memory.
23 / 23
Lazy evaluation
Lazy evaluation evaluates expressions only when they are needed!
Once it has been evaluated, the result is saved for further computation,or discarded if it is not needed in any other running code.
Pros: only the minimal amount of computation is performed duringprogram execution.Cons: all the suspended expressions that have not yet been evaluatedmust be saved in memory.
23 / 23
Lazy evaluation
Lazy evaluation evaluates expressions only when they are needed!
Once it has been evaluated, the result is saved for further computation,or discarded if it is not needed in any other running code.
Pros: only the minimal amount of computation is performed duringprogram execution.
Cons: all the suspended expressions that have not yet been evaluatedmust be saved in memory.
23 / 23
Lazy evaluation
Lazy evaluation evaluates expressions only when they are needed!
Once it has been evaluated, the result is saved for further computation,or discarded if it is not needed in any other running code.
Pros: only the minimal amount of computation is performed duringprogram execution.Cons: all the suspended expressions that have not yet been evaluatedmust be saved in memory.
23 / 23