Presentation is loading. Please wait.

Presentation is loading. Please wait.

Abstracting Repetitions

Similar presentations


Presentation on theme: "Abstracting Repetitions"— Presentation transcript:

1 Abstracting Repetitions
Fold Operations Abstracting Repetitions cs7120(Prasad) L6-FOLD

2 Motivation : Appending lists
lappend (link) generalization of binary append to appending an arbitrary number of lists fun lappend [] = [] | lappend (s::ss) = (lappend ss) lappend : ’a list list -> ’a list cs7120(Prasad) L6-FOLD

3 Properties (Identities)
(map f) o lappend = lappend o (map (map f)) filter p ys) = (filter p (filter p ys) (filter p) o lappend = lappend o (map (filter p)) Efficiency issues and transformations; cf. associative, commutative and distributive laws; Mathematical foundation for code optimization cs7120(Prasad) L6-FOLD

4 Fold Operators Generalize binary operators to n-ary functions (list functions). Abstract specific patterns of recursion / looping constructs. Potential for optimization of special forms. foldl, accumulate, revfold, … foldr, reduce, fold, … foldl1 foldr1 Operator vs infix function vs function cs7120(Prasad) L6-FOLD

5 Foldr (SML97) foldr f a [x1,x2,…,xn] = f( x1 , f(x2, …, f(xn,a)...))
fun foldr f a [] = a | foldr f a (x::xs) = f (x, foldr f a xs) foldr : (’a*’b -> ’b) ->’b -> ’a list -> ’b foldr (op +) 10 [1,2,3] = 16 Normally, f is associative and a is identity wrt f. foldr (op +) a [x1,x2,x3] = ( x1 + ( x2 + ( x3 + a) ) ) ) foldr (op ::) [1,0] [4,3,2] = [4,3,2,1,0] cs7120(Prasad) L6-FOLD

6 Examples foldr (op +) a [x1,x2,x3] = ( x1 + ( x2 + ( x3 + a) ) ) )
[4,3,2,1,0] cs7120(Prasad) L6-FOLD

7 (cont’d) fold in OldML (not suited for partial eval.)
fold : (’a*’b -> ’b) -> ’a list ->’b -> ’b foldr in Bird and Wadler (Curried func.) reduce in Reade foldr : (’a -> ’b -> ’b) -> ’b -> ’a list -> ’b cs7120(Prasad) L6-FOLD

8 Foldl (SML97) foldl f a [x1,x2,…,xn] = f(xn,f(…,f(x2,f(x1,a))…))
fun foldl f a [] = a | foldl f a (x::xs) = foldl f (f(x,a)) xs foldl : (’a*’b -> ’b) ->’b -> ’a list -> ’b foldl (op * ) 10 [1,2,3] = 60 Normally, f is associative and a is identity wrt f. foldl (op *) [x1,x2,…,xn] a = (xn * (…*(x2 * (x1 * a))...)) foldl (op ::) [1,0] [4,3,2] = [2,3,4,1,0] foldl [0] [[1],[2],[3],[4]] = [4,3,2,1,0] fun foldl f a [] = a | foldl f a (x::xs) = foldl f (f(a,x)) xs foldl : (‘b*‘a -> ‘b) ->‘b -> ‘a list -> ‘b cs7120(Prasad) L6-FOLD

9 foldl (op @) [0] [[1],[2],[3],[4]]
Examples foldl (op *) a [x1,x2,…,xn] = (xn * (…*(x2 * (x1 * a))...)) foldl [0] [[1],[2],[3],[4]] [4,3,2,1,0] foldl (op ::) [1,0] [4,3,2] [2,3,4,1,0] cs7120(Prasad) L6-FOLD

10 (cont’d) revfold in OldML (not suited for partial eval.)
revfold : (’b*’a -> ’b) -> ’a list ->’b -> ’b foldl in Bird and Wadler (Curried func.) accumulate in Reade foldl : (’b -> ’a -> ’b) -> ’b -> ’a list ->’b cs7120(Prasad) L6-FOLD

11 Examples fun pack ds = foldl (fn (d,v)=> d+v*10) 0 ds
fun packNot ds = foldl (fn (d,v)=> d*10+v) 0 ds packNot [1,2,3,4] = 100 fun packNott ds = foldr (fn (d,v)=> d+v*10) 0 ds packNott [1,2,3,4] = 4321 Horner’s rule cs7120(Prasad) L6-FOLD

12 foldr (fn (x,xs) => x::xs) [] lis myId [1,2,3,4] = [1,2,3,4]
fun myId lis = foldr (fn (x,xs) => x::xs) [] lis myId [1,2,3,4] = [1,2,3,4] fun myRev lis = foldl (fn (x,xs) => x::xs) [] lis myRev [1,2,3,4] = [4,3,2,1] Foldr preserves ordering, foldl reverses it. cs7120(Prasad) L6-FOLD

13 foldr (fn (x,xs) => if p x then x::xs else xs) [] lis;
fun filter p lis = foldr (fn (x,xs) => if p x then x::xs else xs) [] lis; filter (fn x => x = 2) [1,2,3,2] fun filterNeg p lis = foldl (fn (x,xs) => if p x then xs else filterNeg (fn x => true) [“a”,”b”,”a”] These definitions inspect each element and collect their contribution filterNeg p = filter (not p) Basically these definitions illustrate that both foldl and foldr can be used to define filter. Fun filter p = foldl (fn (x,r) => if p x then else r) [] ; Examples illustrate atypical uses!!! cs7120(Prasad) L6-FOLD

14 foldr (fn (x,xs) => if p x then x::xs else []) [] lis;
fun takewhile p lis = foldr (fn (x,xs) => if p x then x::xs else []) [] lis; takewhile (fn x => x = 2) [2,2,3,1,2] fun dropwhile p lis = foldl (fn (x,xs) => if null xs andalso p x then [] else dropwhile (fn x => true) [1,2,3] takewhile definition using foldr inspects each element of the list from the right and drops the tail if the head element fails the test. It accomplishes the task inefficiently compared to the recursive definition that scans the list from the left. However, contrary to expectation, defining takewhile using foldl is not simple we need to retain the entire suffix irrespective of the value of the element. Similarly, dropwhile has a simple definition in terms of foldl, but not in terms of foldr. fun takewhileX p = foldl version needs additional marker which will restrict the use of the function. fun dropwhileX p = foldr version is not possible because the decision to drop an element in the list depends on the unseen part. cs7120(Prasad) L6-FOLD

15 Generalizing Operators without identity element
E.g., max, min, etc for which basis clause (for []) cannot be defined. fun foldl_1 f (x::xs) = foldl f x xs; fun foldr_1 f (x::[]) = x | foldr_1 f (x::y::ys) = f x (foldr_1 f (y::ys)) cs7120(Prasad) L6-FOLD

16 Laws : Identities If f is a binary function that is associative and a is an identity w.r.t. f, then foldr f a xs = foldl f a (rev xs) foldr [] [[1,2],[3,4],[5]] = [1,2,3,4,5] foldl [] (rev [[1,2],[3,4],[5]]) foldl [] [[1,2],[3,4],[5]] = [5,3,4,1,2] foldr (op +) 0 [1,2,3] = 6 foldl (op +) 0 [1,2,3] = 6 foldl (op +) 0 (rev [1,2,3]) = 6 Reverse not required because of commutativity of +. cs7120(Prasad) L6-FOLD

17 Laws : Identities If f is a binary function that is commutative and a is an identity w.r.t. f, then foldr f a xs = foldl f a xs foldr (op * ) 1 [1,2,3] = 6 foldl (op * ) 1 [1,2,3] = 6 foldr (fn(b,v)=> b andalso v) true [false] = false foldl (fn(b,v)=> b andalso v) true [false] foldr (op +) 0 [1,2,3] = 6 foldl (op +) 0 [1,2,3] = 6 foldl (op +) 0 (rev [1,2,3]) = 6 Reverse not required because of commutativity of +. cs7120(Prasad) L6-FOLD

18 Comparing foldl and foldr.
foldl (op +) 0 [1,2,3] = foldl (op +) 1 [2,3] = foldl (op +) 3 [3] = foldl (op +) 6 [] = 6 (foldl: Efficient) (Tail Recursive) foldr (op +) 0 [1,2,3] =1+foldr (op +) 0 [2,3] =3 + foldr (op +) 0 [3] =6 + foldr (op +) 0 [] foldl and t [t,f,t] = foldl and t [f,t] = foldl and f [t] = foldl and f [] = false (foldr: Efficient) (Short-circuit evaluation) foldr and t [t,f,t] = and t (foldr and t [f,t] = and f (foldr and t [t]) foldl + call by value : tail-recursive optimization (Accumulator technique) foldr + lazy evaluation : short-circuit operation cs7120(Prasad) L6-FOLD

19 scan (processing prefixes)
scan f a [x1,x2,…,xn] = [a,(f a x1),(f (f a x1) x2),…, (f … (f (f a x1) x2) …xn)] fun scan f a [] = [a] | scan f a xs = let val t = (scan f a (init xs)) in [(f (last t) (last xs))] end; scan : (‘a -> ‘b -> ‘a) -> ‘a -> ‘b list -> ‘a list fun scanv f a lis = foldl (fn (x,v) => [(f ((last v), x) )] ) [a] lis; scanv : (‘a * ‘b -> ‘a) -> ‘a -> ‘b list -> ‘a list scanv (op +) 0 [1,2,3,4,5] = [0,1,3,6,10,15] cs7120(Prasad) L6-FOLD


Download ppt "Abstracting Repetitions"

Similar presentations


Ads by Google