04. haskell handling

Post on 11-May-2015

206 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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