190 likes | 360 Views
Fold Operations. Abstracting Repetitions. 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. Properties (Identities).
E N D
Fold Operations Abstracting Repetitions L7fold
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 L7fold
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)) L7fold
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 L7fold
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 L7fold
Examples foldr (op +) a [x1,x2,x3] = ( x1 + ( x2 + ( x3 + a) ) ) ) foldr (op ::) [1,0] [4,3,2] = [4,3,2,1,0] L7fold
(cont’d) • fold in OldML (not suited for partial eval.) fold : (’a*’b -> ’b) -> ’a list ->’b -> ’b • foldrin Bird and Wadler (Curried func.) • reducein Reade foldr : (’a -> ’b -> ’b) -> ’b -> ’a list -> ’b L7fold
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 L7fold
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] L7fold
(cont’d) • revfold in OldML (not suited for partial eval.) revfold : (’b*’a -> ’b) -> ’a list ->’b -> ’b • foldlin Bird and Wadler (Curried func.) • accumulatein Reade foldl : (’b -> ’a -> ’b) -> ’b -> ’a list ->’b L7fold
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] = 4321 L7fold
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] L7fold
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”] L7fold
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] L7fold
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)) L7fold
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 (op @) [] [[1,2],[3,4],[5]] = [1,2,3,4,5] foldl (op @) [] (rev [[1,2],[3,4],[5]]) = [1,2,3,4,5] foldl (op @) [] [[1,2],[3,4],[5]] = [5,3,4,1,2] L7fold
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 L7fold
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 [] = 6 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]) = false Comparing foldl and foldr. L7fold
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 t @ [(f (last t) (last xs))] end; L7fold