Fold Operation

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