1.
Handling Sebastian Rettig“Recursion is important to Haskell because unlike imperative “Recursion is important to Haskell because unlike imperativelanguages, you do computations in Haskell by declaring languages, you do computations in Haskell by declaringwhat 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.
Lets 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 2countX 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.
Lets 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)
Views
Actions
Embeds 0
Report content