04. haskell handling
Post on 11-May-2015
206 Views
Preview:
TRANSCRIPT
Handling
Sebastian Rettig
“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])
“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])
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)
Haskell Features
● Pure Functional Programming Language● Lazy Evaluation ● Pattern Matching and Guards● List Comprehension● Type Polymorphism
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
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
Let's look at the imperative way...
● Imperative
function factorial(n) { int result = 1; if (n == 0) return result; } for (int i=1; i<n; i++) { result *= i; } return result;}
● Recursive
…and translate to the functional way
● Imperative
function fact(n) { int result = 1; if (n == 0) return result; } for (int i=1; i<n; i++) { result *= i; } return result;}
● Recursive
fact 0 = 1fact n = n * fact (n-1)
● and in comparison with the definition:
● BUT imperative also possible:
fact' 0 = 1fact' n = product [1..n]
● compared with the definition:
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 recursionisTrue :: Bool � Bool
isTrue b = b && isTrue b
Recursion (2)● Recursion vs. Final Recursion:
● Hugs> countX 3 [1,4,3,5,3]2
● use accumulator to reduce stack usage
● Hugs> countXFinal 3 [1,4,3,5,3] 0 2
countX :: Int -> [Int] -> IntcountX x [] = 0countX x (y:ys) | x==y = 1 + countX x ys | otherwise = countX x ys
countXFinal :: Int -> [Int] -> Int -> IntcountXFinal x [] accu = accucountXFinal x (y:ys) accu | x==y = countXFinal x ys accu+1 | otherwise = countXFinal x ys accu
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
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:
Let's look at the imperative way...
● Imperative
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;}
● Recursive
…and translate to the functional way ● Imperative
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;}
● Recursive
maxList [] = error “empty”maxList [x] = xmaxList (x:xs) | x > maxTail = x | otherwise = maxTail where maxTail = maxList xs
● or simpler:maxList [] = error “empty”maxList [x] = xmaxList (x:xs) = max x (maxList xs)
● and in comparison with the definition:
Final Recursion
● Get maximum element of list in final recursionmaxFinal :: [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 :)
Simple Recursion Helper
● map
● foldl, foldr, foldl1, foldr1
● scanl, scanr, scanl1, scanr1
● etc...
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]
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
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
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?
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!!!
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):– 3 2 +
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)
top related