# Higher-order functions in ML

Higher-order functions
· A first-order function is one whose
parameters and result are all "data"
· A second-order function has one or more
Iirst-order Iunctions as parameters or result
· In general, a higher-order function has one
or more Iunctions as parameters or result
· ML supports higher-order Iunctions
oubling, revisited
· fun doubIeAII [ ] ~ [ ]
| doubIeAII (h::f) ~ Z ^ h :: (doubIeAII f),
- voI doubIeAII : inf Iisf -· inf Iisf ~ fn
· doubIeAII [I,Z,3,4,b],
- voI if : inf Iisf ~ [Z, 4, o, 8, I0]
· This is the usual heavy use oI recursion
· It's time to simpliIy things
2op
· 2op applies a Iunction to every element oI
a list and returns a list oI the results
· 2op f [x, y, ;] returns [f x, f y, f ;]
· Notice that 2op takes a Iunction as an
argument
· Ignore Ior now the Iact that 2op appears
to take two arguments!
oubling list elements with 2op
· fun doubIe x ~ Z ^ x,
· fun doubIeAII Isf ~ 2op doubIe Isf,
- voI doubIeAII : inf Iisf -· inf Iisf ~ fn
· doubIeAII [I,Z,3,4,b],
- voI if : inf Iisf ~ [Z, 4, o, 8, I0]
· The deIinition oI doubIeAII is simpler, but...
· ...now we need to expose doubIe to the world
nonymous functions
· An anonymous Iunction has the Iorm
(fn 5,r,meter ~· body)
· Now we can deIine doubleAll as
fun doubIeAII Isf ~ 2op (fn x ~· x+x) Isf,
· This Iinal deIinition is simple and doesn't
require exposing an auxiliary Iunction
%he mysterious 2op
· ML Iunctions all take a single argument, but...
· 2op doubIe [I,Z,3] works
· 2op (doubIe, [I,Z,3]) gives a type error
· Even stranger, (2op doubIe) [I,Z,3] works!
· 2op doubIe,
- voI if : inf Iisf -· inf Iisf ~ fn
· 2op doubIe looks like a Iunction...how?
urrying
· In ML, Iunctions are values, and there are
operations on those values
· urrying absorbs a parameter into a
Iunction, creating a new Iunction
· 2op takes one argument (a Iunction), and
returns one result (also a Iunction)
rder of o5er,tions
· fun odd (x, y) ~ x + y,
- voI odd : (inf ^ inf) -· inf ~ fn
· But also consider:
· fun odd x y ~ x + y,
- voI odd : inf -· inf -· inf ~ fn
· odd x y is grouped as (odd x) y
· and inf -· inf -· inf as inf -· (inf -· inf)
riting , curried function I
· fun odd x y ~ x + y,
- voI odd : inf -· inf -· inf ~ fn
That is, odd : inf -· (inf -· inf)
ur new odd takes an inf argument and produces
an (inf -· inf) result
· (odd b) 3, (^ currying hoppens ^)
- voI if : inf ~ 8
riting , curried function II
· MLWorks· voI oddb ~ odd b,
- voI oddb : inf -· inf ~ fn
Notice the use oI voI, we are manipulating values
· MLWorks· oddb 3, (^ use our new fn ^)
- voI if : inf ~ 8
unction com5osition
· The Iunction composition operator is the
inIix lowercase letter o
· (f o g) x gives the same result as f(g(x))
· But composition gives you a way to bundle
the Iunctions Ior later use; f(g(x)) requires
an argument x right now
· voI h ~ f o g, is perIectly legal ML
efining higher-order functions I
· fun oppIyI(f, x) ~ f(x),
- voI oppIyI : ((´o -· ´b) ^ ´o) -· ´b ~ fn
· oppIyI (fI, [I,Z,3]),
- voI if : inf Iisf ~ [Z, 3]
· But:
· oppIyI fI [I,Z,3],
- error: Funcfion oppIied fo orgu2enf of
wrong fype
efining higher-order functions II
· fun oppIyZ f x ~ f(x),
- voI oppIyZ : (´o -· ´b) -· ´o -· ´b ~ fn
· oppIyZ fI [I,Z,3],
- voI if : inf Iisf ~ [Z, 3]
· oppIyZ (fI, [I,Z,3]),
- error: Funcfion oppIied fo orgu2enf of
wrong fype
· Advantage: this Iorm can be curried
useful function. spon
· spon Iinds elements at the Iront oI a list that
satisIy a given predicate
· Example:
· spon even [Z,4,o,7,8,9,I0] gives [Z, 4, o]
· spon isn't a built-in; we have to write it
Im5lementing spon
· fun spon f L ~
if f(hd L)
fhen (hd L) :: spon f (fI L)
eIse [],
· spon even [Z,4,o,7,8,9,I0],
- voI if : inf Iisf ~ [Z, 4, o]
tending spon: sponZ
· spon returns the elements at the Iront oI a
list that satisIy a predicate
· Suppose we extend it to also return the
remaining elements
· We can do it with the tools we have, but
more tools would be convenient
ener,li:ed ,ssignment
· voI (o, b, c) ~ (8, 3, o),
- voI o : inf ~ 8
voI b : inf ~ 3
voI c : inf ~ o
· voI x::xs ~ [I,Z,3,4],
- voI x : inf ~ I
voI xs : inf Iisf ~ [Z, 3, 4]
· Generalized assignment is especially useIul
when a Iunction returns a tuple
efining loc,l v,lues with Ief
· Ief
decIorofion ,
decIorofion ,
. . .
in
expression
end
· Ief helps avoid redundant computations
,m5le of Ief
fun circIeAreo (rodius) ~
Ief
voI pi ~ 3.I4Io,
fun squore x ~ x ^ x
in
pi ^ squore (rodius)
end,
Im5lementing sponZ
· fun sponZ f Iisf ~
if f(hd Iisf) fhen
Ief voI (firsf, second) ~ sponZ f (fI Iisf)
in ((hd Iisf :: firsf), second)
end
eIse ([], Iisf),
- voI sponZ : (´o -· booI) -· ´o Iisf -· (´o Iisf ^ ´o Iisf) ~
fn
· sponZ even [Z,4,o,7,8,9,I0],
- voI if : (inf Iisf ^ inf Iisf) ~ ([Z, 4, o], [7, 8, 9, I0])
nother built-in function. porfifion
· Partition breaks a list into two lists: those
elements that satisIy the predicate, and
those that don't
· Example:
· porfifion even [Z,4,o,7,8,9,I0],
- voI if : (inf Iisf ^ inf Iisf) ~ ([Z, 4, o, 8,
I0], [7, 9])
"uicksort
· Choose the Iirst element as a 5ivot.
or [3,I,4,I,b,9,Z,o,b] choose 3 as the pivot
· Break the list into elements ·÷ pivot, and
elements ~ pivot:
- [I, I, Z] and [4, b, 9, o, b]
· Quicksort the sublists:
- [I, I, Z] and [4, b, b, o, 9]
· Append the sublists with the pivot in the middle:
- [I, I, Z, 3, 4, b, b, o, 9]
"uicksorf in ML
· fun quicksorf [ ] ~ [ ]
| quicksorf (x :: xs) ~
Ief voI (fronf, bock) ~ porfifion (fn n ~· n ·~ x) xs
in (quicksorf fronf) Ç (x :: (quicksorf bock))
end,
- voI quicksorf : inf Iisf -· inf Iisf ~ fn
· quicksorf [3,I,4,I,b,9,Z,o,b,3,o],
- voI if : inf Iisf ~ [I, I, Z, 3, 3, 4, b, b, o, o, ..]
foIdI
· foIdI op bosis Iisf repeatedly computes
(element op b,sis), starting with the basis and
using the list elements starting Irom the left
· foIdI (op -) I0000 [I, Z0, 300, 4000],
- voI if : inf ~ I37I9
· (4000 - (300 - (Z0 - (I - I0000)))),
- voI if : inf ~ I37I9
foIdr
· foIdr op bosis Iisf repeatedly computes
(element op b,sis), starting with the basis and
using the list elements starting Irom the right
· foIdr (op -) I0000 [I, Z0, 300, 4000],
- voI if : inf ~ oZ8I
· (I - (Z0 - (300 - (4000 - I0000)))),
- voI if : inf ~ oZ8I
%esting if , list is sorted
· The Iollowing code tests iI a list is sorted:
· fun sorfed [] ~ frue
| sorfed [_] ~ frue
| sorfed (x::y::resf) ~
x ·~ y ondoIso sorfed (y::resf),
· This applies a (boolean) test to each adjacent
pair oI elements and "ANDs" the results
· Can we generalize this Iunction?
ener,li:ing the sorfed 5redic,te
· fun sorfed [] ~ frue
| sorfed [_] ~ frue
| sorfed (x::y::resf) ~
x ·~ y ondoIso sorfed (y::resf),
· The underlined part is the only part speciIic
to this particular Iunction
· We can replace it with a predicate passed in
as a parameter
poirwise
· fun poirwise f [] ~ frue
| poirwise f [_] ~ frue
| poirwise f (x::y::resf) ~
f(x,y) ondoIso poirwise f (y::resf),
· Here are the changes we have made:
Changed the name Irom sorfed to poirwise
changed x ·~ y to f(x, y)
&sing poirwise
· poirwise (op ·~) [I, 3, b, b, 9],
- voI if : booI ~ frue
· poirwise (op ·~) [I, 3, b, 9, b],
- voI if : booI ~ foIse
· poirwise (fn (x, y) ~· x ~ y - I) [3,4,b,o,7],
- voI if : booI ~ frue
· poirwise (fn (x, y) ~· x ~ y - I) [3,4,b,7],
- voI if : booI ~ foIse
%he nd

07
47/071:3.9438
W 1789
47/071:3.943 8430480 5,7,209078,3/708:9,70,/,9, W 80.43/
47/071:3.943 ,8430472470 1789
47/071:3.9438,85,7,20907847708:9 W 30307, ,07
47/071:3.943 ,8430 4724701:3.9438,85,7,20907847708:9 W 8:55479807
47/071:3.9438