cs5205: foundation in programming languages

40
CS5205 Haskell 1 CS5205: Foundation in Programming Languages Basics of Functional Programming.

Upload: frayne

Post on 19-Jan-2016

42 views

Category:

Documents


0 download

DESCRIPTION

CS5205: Foundation in Programming Languages. Basics of Functional Programming. Topics. Higher-Order Functions Formal Reasoning Abstraction vs Efficiency Bridging the Divide. Function Abstraction. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: CS5205: Foundation in  Programming Languages

CS5205 Haskell 1

CS5205: Foundation in Programming Languages

Basics ofFunctional Programming.

Page 2: CS5205: Foundation in  Programming Languages

CS5205 Haskell 2

TopicsTopics

• Higher-Order Functions• Formal Reasoning• Abstraction vs Efficiency• Bridging the Divide

Page 3: CS5205: Foundation in  Programming Languages

CS5205 Haskell 3

Function AbstractionFunction Abstraction

• Function abstraction is the ability to convert any expression into a function that is evaluated at a later time.

<Expr>

Normal Execution

time

p = \ () -> Expr

p ()

Delayed Execution

time

Page 4: CS5205: Foundation in  Programming Languages

CS5205 Haskell 4

Higher-Order FunctionsHigher-Order Functions

• Higher-order programming treats functions as first-class, allowing them to be passed as parameters, returned as results or stored into data structures.

• This concept supports generic coding, and allows programming to be carried out at a more abstract level.

• Genericity can be applied to a function by letting specific operation/value in the function body to become parameters.

Page 5: CS5205: Foundation in  Programming Languages

CS5205 Haskell 5

GenericityGenericity• Replace specific entities (0 and +) by parameters.

sumList ls = case ls of [] -> 0 x:xs -> x+(sumList xs)

foldr f u ls = case ls of [] -> u x:xs -> f x (foldr f u xs)

Page 6: CS5205: Foundation in  Programming Languages

CS5205 Haskell 6

Polymorphic, Higher-Order TypesPolymorphic, Higher-Order Types

sumList :: [Int] -> Int

sumList :: Num a => [a] -> a

foldr :: (a -> b -> b) -> b -> [a] -> b

Page 7: CS5205: Foundation in  Programming Languages

CS5205 Haskell 7

Instantiating Generic FunctionsInstantiating Generic Functions

sumL2 :: Num a => [a] -> asumL2 ls = foldr (+) 0 ls

sumL2 [1, 2, 3] )

sumL2 [1.1, 3, 2.3] )

Page 8: CS5205: Foundation in  Programming Languages

CS5205 Haskell 8

Instantiating Generic FunctionsInstantiating Generic Functions

prodL :: Num a => [a] -> aprodL ls = foldr (*) 1 ls

prodL [1, 2, 5] )

prodL [1.1, 3, 2.3] )

Page 9: CS5205: Foundation in  Programming Languages

CS5205 Haskell 9

Instantiating Generic FunctionsInstantiating Generic Functions

map :: (a -> b) -> [a] -> [b]map f [] = []map f (x:xs) = (f x) : (map f xs)

map f xs = foldr … … … xs

• Can you express map in terms of foldr?

Page 10: CS5205: Foundation in  Programming Languages

CS5205 Haskell 10

Instantiating Generic FunctionsInstantiating Generic Functions

filter :: (a -> Bool) -> [a] -> [a]filter f [] = []filter f (x:xs) =

if (f x) then x : (filter f xs)else filter f xs

• Filtering a list of elements with a predicate.

filter f xs = foldr … … … xs

• Can we express filter in terms of foldr?

Page 11: CS5205: Foundation in  Programming Languages

CS5205 Haskell 11

Pipe/ComposePipe/Compose

compose :: (b -> c) -> (a -> b)-> a -> c

compose f g = \ x -> f (g x)g | f = compose f g

cmd1 | cmd2

• Similar to Unix pipe command:

Page 12: CS5205: Foundation in  Programming Languages

CS5205 Haskell 12

Iterator Construct Iterator Construct

for :: Int -> Int -> (Int -> a -> a) -> a -> a

for i j f a = if i>j then aelse for (i+1) j (f i a)

for :: Num b, Ord b => b -> b ->(b -> a -> a) -> a -> a

• In Haskell, type class help give a more generic type:

Page 13: CS5205: Foundation in  Programming Languages

CS5205 Haskell 13

Right Folding Right Folding

foldr f u [x1,x2,..,xn]

f x1 (foldr f u [x2 ..xn]) f x1 (f x2 (fold f u [x3..xn]))

f x1 (f x2 (… (fold f u [xn]) …)) f x1 (f x2 (… (f xn u) …)))

associate to right

Page 14: CS5205: Foundation in  Programming Languages

CS5205 Haskell 14

Left Folding – Tail Recursion Left Folding – Tail Recursion

• Accumulate result in a parameter:

foldl f u ls = case ls of [] -> u x:xs -> foldl f (f u x) xs

• What is the type of foldl?

• Can we compute factorial using it?

based on accumulation

Page 15: CS5205: Foundation in  Programming Languages

CS5205 Haskell 15

Left Folding Left Folding

foldl f u [x1,x2,..,xn]

foldl f (f u x1) [x2 ..xn] foldl f (f (f u x1) x2) [x3..xn]))

foldl f (f … (f (f u x1) x2)… xn) [] f (… (f (f u x1) x2) …) xn

left is here!

Page 16: CS5205: Foundation in  Programming Languages

CS5205 Haskell 16

Instance of Left FoldingInstance of Left Folding• Summing a list by accumulation.

sumT acc ls = case ls of [] -> 0 x:xs -> sumT (x+acc) xs

sumList ls = sumT 0 ls

sumT acc ls = foldl (+) acc ls

Page 17: CS5205: Foundation in  Programming Languages

CS5205 Haskell 17

Referential TransparencyReferential Transparency

• An expression is referentially transparent if it can always be replaced by an equivalent expression with the same value and effect. Allows reasoning based on components.

• Useful for:• simplifying algorithm• proving correctness• optimization + parallelization

• Pure functions are referentially transparent, as relied on in mathematical reasoning.

Page 18: CS5205: Foundation in  Programming Languages

CS5205 Haskell 18

Equivalence Proof Equivalence Proof • Can we Prove : sumList xs = sumT 0 xs.

• Generalise : (sumList xs)+a = sumT a xs.

• By InductionCase : x=[] (sumList [])+a = sumT a []

0+a = aCase : x=x:xs (sumList x:xs)+a = sumT a (x:xs) x+(sumList xs)+a = sumT (x+a) xs (sumList xs)+(x+a) = sumT (x+a) xs

// apply induction hypothesis

Page 19: CS5205: Foundation in  Programming Languages

CS5205 Haskell 19

List ReversalList Reversal• Concatenate first element to last position.

rev [] = []rev (x:xs) = rev xs ++ [x]

rev xs = foldr … … …

What is the time complexity?

Page 20: CS5205: Foundation in  Programming Languages

CS5205 Haskell 20

Time Complexity Time Complexity • Assume : CC(xs++ys) = length xs Derive :StepsSteps(rev(xs))

• Case [] : StepsSteps(rev([])) = 1+StepsSteps([])

= 1+0 • Case x:xs : StepsSteps(rev(x:xs))

= 1+StepsSteps(rev(xs)++[a])= 1+CC(rev(xs)++_)+StepsSteps(rev(xs))= 1+length(rev(xs)+StepsSteps(rev(xs))= 1+length(xs)+StepsSteps(rev(xs))

• Thus : CC(rev(xs)) = (length xs)^2

Page 21: CS5205: Foundation in  Programming Languages

CS5205 Haskell 21

Iterative List ReversalIterative List Reversal• Concatenate first element to last position.

revT w [] = wrevT w (x:xs) = revT (x:w) xs

Same as:revT w xs = foldl (\ w x -> x:w) w xs

What is the time complexity?

Page 22: CS5205: Foundation in  Programming Languages

CS5205 Haskell 22

Time Complexity Time Complexity • Derive StepsSteps(revT w xs)

• Case [] : StepsSteps(revT w []) = 1+StepsSteps(w)

= 1+0 • Case x:xs : StepsSteps(revT w (x:xs))

= 1+StepsSteps(revT (x:w) xs)= 1+StepsSteps(revT _ xs)

• Thus : CC(revT w xs) = (length xs)

Page 23: CS5205: Foundation in  Programming Languages

CS5205 Haskell 23

Abstraction vs Efficiency Abstraction vs Efficiency

• Abstraction helps with programmers’ productivity

• Efficiency helps machine execution.

• Tension between abstraction and efficiency

• Abstract program • stress on ‘what’ rather than ‘how’• typically uses simpler (maybe naïve) algorithm

• Efficient program• optimised implementation• use of clever programming techniques

Page 24: CS5205: Foundation in  Programming Languages

CS5205 Haskell 24

Bridging the DivideBridging the Divide

Abstract Code/Specs

Efficient Codeor Implementation

transform orsynthesize verify

Page 25: CS5205: Foundation in  Programming Languages

CS5205 Haskell 25

Unfold/Fold TransformationUnfold/Fold Transformation

• DEFINE - new function definition

• UNFOLD – replace a call by its body

• FOLD – replace an expression matching the RHS of a definition by its corresponding call

• INSTANTIATE – provide special cases of a given equation.

• ABSTRACT – introduce a tuple of expressions

• LAW – application of valid lemma, e.g. associativity

Page 26: CS5205: Foundation in  Programming Languages

CS5205 Haskell 26

Fusion Transformation Fusion Transformation • Consider:

…sum (double xs)…sum [] = 0sum x:xs = x+(sum xs)double [] = []double x:xs = 2*x : (double xs)

• Computation reuses smaller functions to build larger ones but may result in unnecessary intermediate structures. They can cause space overheads.

• Solution : Fuse the code together!

Page 27: CS5205: Foundation in  Programming Languages

CS5205 Haskell 27

Fusion Transformation Fusion Transformation • Define:

sumdb xs = sum (double xs)

• Instantiate: xs=[]sumdb [] = sum (double [])

= sum []= 0

• Instantiate: xs=x:xssumdb x:xs = sum (double x:xs)

= sum (2*x : double xs)

= 2*x + sum(double xs)= 2*x + (sumdb xs)

Page 28: CS5205: Foundation in  Programming Languages

CS5205 Haskell 28

Iteration Transformation Iteration Transformation

• Define:sumdbT a xs = a+(sumdb xs)

• Instantiate: xs=[]sumdbT a [] = a+(sumdb [])

= a

• Instantiate: xs=x:xssumdbT a (x:xs) = a+(sumdb x:xs)

= a+(2*x + sumdb xs)= (a+2*x) + (sumdb xs)= sumdbT (a+2*x) xs

Page 29: CS5205: Foundation in  Programming Languages

CS5205 Haskell 29

Laziness vs Strictness Laziness vs Strictness • Laziness increase expressiveness, allowing infinite data

structures, by not evaluating each subexpression until it is really needed.

• However, there is a performance penalty (both space and time), as the suspended computation has to be stored as a closure and then invoked subsequently.

• If you always need some of the parameters, we might as well evaluate their corresponding arguments first.

• Question : When is an argument to a function needed (strict)? Using ? to denote non-termination.

f … ? … = ?

Page 30: CS5205: Foundation in  Programming Languages

CS5205 Haskell 30

Strictness TransformationStrictness Transformation• Can analyse that accumulating argument of sumdb is

strict. We can force strictness using the `seq` operator.

sumdbT a [] = asumdbT a (x:xs) = sumdbT (a+2*x) xs

sumdbT a [] = asumdbT a (x:xs) = let p = a+2*x in

p `seq` sumdbT p xs

Page 31: CS5205: Foundation in  Programming Languages

CS5205 Haskell 31

Tupling Transformation Tupling Transformation • Average of a List :

average xs = sum xs / length xs

• Define : both xs = (sum xs, length xs)

• Instantiate : both [] = (sum [], length [])

= (0,0)• Instantiate :

both x:xs = (sum x:xs, length x:xs)= (x+sum xs, 1+length xs)= let (u,v)= (sum xs,length xs) in

(x+u, 1+v)= let (u,v)= both xs in u/v

Page 32: CS5205: Foundation in  Programming Languages

CS5205 Haskell 32

Naive FibonacciNaive Fibonacci• Natural but inefficient version of fibonacci :

fib 0 = 1fib 1 = 1fib n = (fib n-1)+(fib n-2)

• Time complexity is exponential time due to presence of redundant calls.

Page 33: CS5205: Foundation in  Programming Languages

CS5205 Haskell 33

A Call Tree of fibfib 6

fib 5 fib 4

fib 4 fib 3 fib 3 fib 2

fib 3 fib 2 fib 2 fib 1 fib 2 fib 1

Many repeated calls!

Page 34: CS5205: Foundation in  Programming Languages

CS5205 Haskell 34

A Call Graph of fibfib 6

fib 5

fib 4

fib 3

fib 2

fib 1

No repeated call through reuse of identical calls

Page 35: CS5205: Foundation in  Programming Languages

CS5205 Haskell 35

Tupling - Computing Two Results

Compute two calls from next two calls in hierarchy:((fib n) , (fib n-1))

((fib n-1) , (fib n-2))

Page 36: CS5205: Foundation in  Programming Languages

CS5205 Haskell 36

Tupling Fibonacci Tupling Fibonacci

• Define : fibtup n = (fib n+1, fib n)

• Instantiate : fibtup 0 = (fib 1, fib 0)

= (1,1)

• Instantiate : fibtup n+1 = (fib n+2, fib n+1)

= ((fib n+1)+(fib n), fib n+1)= let (u,v)= (fib n+1, fib n) in (u+v, u)= let (u,v)= fibtup n in (u+v, u)

Page 37: CS5205: Foundation in  Programming Languages

CS5205 Haskell 37

Using the Tupled Function Using the Tupled Function

fib 0 = 1fib 1 = 1fib n = fib n-1 + fib n-2

= let (u,v) = (fib n-1,fib n-2)

in u+v = let (u,v) = fibtup (n-2)

in u+v

Page 38: CS5205: Foundation in  Programming Languages

CS5205 Haskell 38

Linear Recursion

fib 6

fib 5

fib 4

fib 3

fib 2

fib 1

fibtup 0 = (1,1)fibtup (n+1) =

let (u,v)= fibtup n

in (u+v,u)

Page 39: CS5205: Foundation in  Programming Languages

CS5205 Haskell 39

To Iteration

fib 6

fib 5

fib 4

fib 3

fib 2

fib 1

fibT 0 u v= (u,v)

fibT (n+1) u v = fibT n (u+v,u)

Page 40: CS5205: Foundation in  Programming Languages

CS5205 Haskell 40

OptimizationOptimization

• Should be done only if critical.

• Should be automated where possible, for e,g. as part of compilation.

• Manual optimization by human should preferably be carefully checked or verified