1. Handling
Sebastian Rettig
“Recursion is important to Haskell because unlike imperative
“Recursion is important to Haskell because unlike imperative
languages, you do computations in Haskell by declaring
languages, you do computations in Haskell by declaring
what something is instead of declaring how you get it.” ([1])
what something is instead of declaring how you get it.” ([1])
2. Functional Programming
● No Variables
● Functions only, eventually stored in
Modules
– Behavior do not change, once defined
– → Function called with same parameter
calculates always the same result
● Function definitions (Match Cases)
● Recursion (Memory)
3. Haskell Features
● Pure Functional Programming Language
● Lazy Evaluation
● Pattern Matching and Guards
● List Comprehension
● Type Polymorphism
4. How to write Functions?
● eventually think about imperative function
● and translate into recursive function
● → generally the same schema to go for:
– 1. define simple cases (recursion anchor)
– 2. define the recursion call
● lets start with imperative functions
5. How to implement the Factorial?
● Remember:
“Recursion is important to Haskell because unlike imperative
languages, you do computations in Haskell by declaring what
something is instead of declaring how you get it.” ([1])
● Okay, then look at the definition:
– Imperative definition
– Recursive definition
6. Let's look at the imperative way...
● Imperative ● Recursive
function factorial(n) {
int result = 1;
if (n == 0)
return result;
}
for (int i=1; i<n; i++) {
result *= i;
}
return result;
}
7. …and translate to the functional way
● Imperative ● Recursive
function fact(n) { fact 0 = 1
int result = 1; fact n = n * fact (n-1)
if (n == 0) ● and in comparison with the definition:
return result;
}
for (int i=1; i<n; i++) {
result *= i;
} ● BUT imperative also possible:
return result;
fact' 0 = 1
}
fact' n = product [1..n]
● compared with the definition:
8. Recursion (1)
● we have no loops → use Recursion:
myMap :: Int -> [Int] -> [Int]
myMap v [] = [] -- Recursion Anchor!
myMap v (x:xs) = [v*x] ++ myMap v xs
● Recursion Anchor contains the break rule
– endless loop = anchorless recursion
isTrue :: Bool Bool
isTrue b = b && isTrue b
9. Recursion (2)
● Recursion vs. Final Recursion:
countX :: Int -> [Int] -> Int ● Hugs> countX 3 [1,4,3,5,3]
countX x [] = 0 2
countX x (y:ys)
| x==y = 1 + countX x ys
| otherwise = countX x ys
countXFinal :: Int -> [Int] -> Int -> Int
countXFinal x [] accu = accu
countXFinal x (y:ys) accu
| x==y = countXFinal x ys accu+1
| otherwise = countXFinal x ys accu
● use accumulator to reduce stack usage
● Hugs> countXFinal 3 [1,4,3,5,3] 0
2
10. Where & let .. in
● additional definitions
● let .. in defines scope of usage
– let = definition
– in = scope of definition
– e.g.: add x = let a=9 in a + x
● where has scope in whole function
– e.g.: add x = a + x
where a=9
11. The maximum value of a List?
● Remember:
“Recursion is important to Haskell because unlike imperative
languages, you do computations in Haskell by declaring what
something is instead of declaring how you get it.” ([1])
● Okay, then look at the definition:
12. Let's look at the imperative way...
● Imperative ● Recursive
function max(array list) {
if (empty(list)) {
throw new Exception();
}
max = list[0]
for (int i=0; i<length(list);
i++) {
if (list[i] > max) {
max = list[i];
}
}
return max;
}
13. …and translate to the functional way
● Imperative ● Recursive
function max(array list) { maxList [] = error “empty”
if (empty(list)) { maxList [x] = x
throw new Exception(); maxList (x:xs)
} | x > maxTail = x
max = list[0] | otherwise = maxTail
for (int i=0; i<length(list); where maxTail = maxList xs
i++) {
if (list[i] > max) {
● or simpler:
max = list[i]; maxList [] = error “empty”
} maxList [x] = x
} maxList (x:xs) =
return max; max x (maxList xs)
} ● and in comparison with the
definition:
14. Final Recursion
● Get maximum element of list in final recursion
maxFinal :: [Int] -> Int -> Int
maxFinal [] accu = accu
maxFinal (x:xs) accu
| x > accu = maxFinal xs x
| otherwise = maxFinal xs accu
● often the same Schema to program
● → there exist functions in haskell to simplify the
all day work :)
16. Lambda Functions
● often called as Inline Functions in other
languages
● Syntax:
– <param> <param> → <operation>
– e.g.:
a b -> a+b
– map (x -> x+3) [2,3,4]
● returns [5,6,7]
17. Folding, Scanning (1)
● e.g.: How to get the max of an array?
– imperative:
int max = 0;
foreach (entry in list) {
max = (entry > max) ? entry : max;
}
– functional:
let list = [8,6,4,1,7,3,5]
foldl (acc x -> if x > acc then x else acc) 0 list
18. Folding, Scanning (2)
● scan shows the accumulator state on
every recursion step:
scanl (acc x -> if x > acc then x else acc) 0 list
– returns:
[0,8,8,8,8,8,8,8]
– good for debugging
– good to understand recursion
19. Folding, Scanning (3)
● foldl versus foldr:
– first we look at the Header of the functions:
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
– What is the difference?
20. Folding, Scanning (4)
● foldl versus foldr:
– first we look at the Header of the functions:
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
– What is the difference?
● accumulator and parameter are
switched!!!
21. Infix, Prefix, Postfix
● Infix (usable in Haskell):
– 2 + 3
– 2 `mod` 3
● Prefix (usable in Haskell):
– (+) 2 3
– mod 2 3
● Postfix (used in stack machines):
– 32+
22. Sources
[1] Haskell-Tutorial: Learn you a Haskell (http://learnyouahaskell.com/,
2012/03/15)
[2] The Hugs User-Manual (
http://cvs.haskell.org/Hugs/pages/hugsman/index.html, 2012/03/15)
[3] The Haskellwiki (http://www.haskell.org/haskellwiki, 2012/03/15)