Fold Operations Abstracting Repetitions cs776(Prasad) L7fold 1 Motivation : Appending lists • lappend (link) – generalization of binary append to appending an arbitrary number of lists fun lappend [] = [] | lappend (s::ss) = s @ (lappend ss) lappend : ’a list list -> ’a list cs776(Prasad) L7fold 2 Properties (Identities) (map f) o lappend = lappend o (map (map f)) filter p (xs @ ys) = (filter p xs) @ (filter p ys) (filter p) o lappend = lappend o (map (filter p)) cs776(Prasad) L7fold 3 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 cs776(Prasad) L7fold 4 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 +) cs776(Prasad) 10 [1,2,3] = 16 L7fold 5 Examples foldr (op +) a [x1,x2,x3] = ( x1 + ( x2 + ( x3 + a) ) ) ) foldr (op ::) [1,0] [4,3,2] = [4,3,2,1,0] cs776(Prasad) L7fold 6 (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 cs776(Prasad) L7fold 7 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 * ) cs776(Prasad) 10 [1,2,3] = 60 L7fold 8 Examples foldl (op *) a [x1,x2,…,xn] = (xn * (…*(x2 * (x1 * a))...)) foldl (op @) [0] [[1],[2],[3],[4]] = [4,3,2,1,0] foldl (op ::) [1,0] [4,3,2] = [2,3,4,1,0] cs776(Prasad) L7fold 9 (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 cs776(Prasad) L7fold 10 Examples fun pack ds = foldl (fn (d,v)=> d+v*10) 0 ds pack [1,2,3,4] = 1234 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] cs776(Prasad) = 4321 L7fold 11 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] cs776(Prasad) L7fold 12 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 xs@[x]) [] lis; filterNeg (fn x => true) [“a”,”b”,”a”] cs776(Prasad) L7fold 13 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 xs else xs@[x]) [] lis; dropwhile (fn x => true) [1,2,3] cs776(Prasad) L7fold 14 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)) cs776(Prasad) L7fold 15 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 = foldl = foldl = cs776(Prasad) (op @) [] [[1,2],[3,4],[5]] [1,2,3,4,5] (op @) [] (rev [[1,2],[3,4],[5]]) [1,2,3,4,5] (op @) [] [[1,2],[3,4],[5]] [5,3,4,1,2] L7fold 16 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] = false cs776(Prasad) L7fold 17 Comparing foldl and foldr. foldl (op +) 0 = foldl (op +) = foldl (op +) = foldl (op +) = 6 [1,2,3] 1 [2,3] 3 [3] 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 [] = 6 cs776(Prasad) foldl and t = foldl and = foldl and = foldl and = false [t,f,t] t [f,t] f [t] f [] (foldr: Efficient) (Short-circuit evaluation) foldr and t [t,f,t] = and t (foldr and t [f,t] = and f (foldr and t [t]) = false L7fold 18 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 [] | scan f a xs let val t in t @ end; cs776(Prasad) = [a] = = (scan f a (init xs)) [(f (last t) (last xs))] L7fold 19
© Copyright 2026 Paperzz