Programming Languages: Chapter 8: Currying and Higherorder Functions
Variablelength argument lists in Scheme
Arguments to any function are always passed in as list.
It is up to the programmer to decompose that argument list
and group individual arguments
in the formal parameter specification of the function definition
using dot notation, if necessary.
(define f (lambda (x) x))
(f 1)
(f '(1 2 3))
;;; x is just the list (1 2 3)
(define f (lambda x x))
(f 1 2 3)
(f 1)
;;; uses pattern matching like ML and Haskell
;;; g and h take a variable number of arguments
(define g (lambda (x . y) x))
(define h (lambda (x . xs) xs))
;;; only 1 argument passed
(g '(1 2 3))
(h '(1 2 3))
(write "a")
(newline)
;;; now 2 arguments passed
(g 1 '(2 3))
(h 1 '(2 3))
;;; now 3 arguments passed
(g 1 2 3)
(h 1 2 3)
Kleene's S_{mn} theorem
 also known as the translation lemma,
parameter theorem, or parameterization theorem from
computability theory
 formally, states that for any function
f (x_{1}, x_{2}, ..., x_{n}),
f (a_{1}, a_{2}, ..., a_{m})
=
g (x_{m+1}, x_{m+2}, ..., x_{n}),
where m < n, such that
g (a_{m+1}, a_{m+2}, ..., a_{n}) =
f (a_{1}, a_{2}, ..., a_{m},
a_{m+1}, a_{m+2}, ...,
a_{n}).
Curried form in Haskell
pow (0, _) = 1
pow (1, b) = b
pow (_, 0) = 0
pow (e, b) = b * pow (e1, b)
powc 0 _ = 1
powc 1 b = b
powc _ 0 = 0
powc e b = b * powc (e1) b
 notice anything interesting?
Main> :type pow
pow :: (Num a, Num b) => (b,a) > a
Main> :type powc
powc :: (Num a, Num b) => b > a > a
square = powc 2
cube = powc 3
 notice anything interesting?
Prelude> :type map
map :: (a > b) > [a] > [b]
Prelude> :type foldl
foldl :: (a > b > a) > a > [b] > a
Prelude> :type foldr
foldr :: (a > b > b) > b > [a] > b
Prelude>
parenthesizing an operator converts it from an infix to prefix operator:
 called a 'section'
inc = (+) 1
inc1 = (+) 1.0
Main> :type inc
inc :: Integer > Integer
Main> :type inc1
inc1 :: Double > Double
Main>
 [PIH] p. 118
 currying obviates the need for
 the helper function insertineach
powerset [] = [[]]
powerset (x:xs) =
let
temp = powerset xs
in
(map (x:) temp) ++ temp
Main> :type powerset
powerset :: [t] > [[t]]
functions curry and uncurry
Prelude> :type curry
curry :: ((a, b) > c) > a > b > c
Prelude> :type uncurry
uncurry :: (a > b > c) > (a, b) > c
Curried form in ML
(same as in Haskell)
fun pow 0 _ = 1
 pow 1 b = b
 pow _ 0 = 0
 pow e b = b * pow (e1) b;
(*
int * int > int
=>
int > int > int
*)
val square = pow 2;
val cube = pow 3;
map, foldl, are foldr are defined in
curried form:
val ourimplode = foldr (op ^) "" o (map str);
(* notice something peculiar about foldr and map *)
see [EMLP] Chapter 5 and, specifically § 5.5 (pp. 168173),
for more information.
Curried Form in Scheme
 any language with firstclass closures can be used to define
functions in curried form
 first attempt:
;;; here the curried form is too tightly woven into the function definition
;;; moreover, pow now cannot be completely evaluated
(define pow
(lambda (e)
(cond
((eqv? e 0) 1)
(else
;; return a closure
(lambda (b)
(cond
((eqv? b 0) 0)
((eqv? b 1) 1)
((eqv? e 1) b)
(else (* b ((pow ( e 1)) b)))))))))
> (define square (pow 2))
> (square 4)
16
 second attempt:
(define s11
(lambda (f x)
(list 'lambda '(y) (list f x 'y))))
(define pow
(lambda (e b)
(cond
((eqv? b 0) 0)
((eqv? b 1) 1)
((eqv? e 0) 1)
((eqv? e 1) b)
(else (* b (pow ( e 1) b))))))
> (define square (s11 pow 2))
> square
(lambda (y) (#<procedure:pow> 2 y))
> (eval square)
#<procedure>
> ((eval square) 4)
16
 a similar approach:
;;; notice we must explicitly call papplyn which
;;; means we must know apriori how many arguments are contained
;;; in the complete argument list of the function we desire to partially apply
;;; however, this approach obviates the need explicitly to call eval and
;;; the need define multiple versions of s (e.g., to partially apply
;;; a 3 argument function in all ways possible would require
;;; s111, s12, and s21).
(define papplyn
(lambda (fun . args)
(lambda x
(apply fun (append args x)))))
(define square (papplyn pow 2))
> (square 4)
16
;; examples from Jeffrey A. Meunier's article ``Function Currying in Scheme''
;; and we can continue to partially apply the result as we desire
(define list1 (papplyn list 'A))
(define list2 (papplyn list1 'tree))
(define list3 (papplyn list2 'grows))
(list3 'in 'Brooklyn.)
;; since the original function (which is list)
;; can accept multiple arguments,
;; the partially applied function can also accept multiple arguments
(define list4 (papplyn list 'A 'tree 'grows))
(list4 'in 'Brooklyn.)
Partial evaluation
Generalizes the idea of currying from any prefix of the
argument list to any subset of the argument list.
Formally, states that for any function
f(x_{1}, x_{2}, ..., x_{n}),
f(a, b, ..., r)
=
g({x_{1}, x_{2}, ..., x_{n}}  {a, b, ..., r}),
where
{a, b, ..., r} ⊆
{x_{1}, x_{2}, ..., x_{n}},
such that
g(s, t, ..., z) =
f(a, b, ..., z).
Haskell
ourmap f [] = []
ourmap f (x:xs) = (f x):(ourmap f xs)
square n = n*n
ans = ourmap square [1,2,3,4,5,6]
squarelist lon = map square lon
ans2 = squarelist [1,2,3,4,5,6]
vs.
squarelist = map square
Functional composition
Haskell's composition operator is .
add3 x = x+3
mult2 x = x*2
add3_then_mult2 = mult2 . add3
mult2_then_add3 = add3 . mult2
ans3 = add3_then_mult2 3
ans4 = mult2_then_add3 3
Fooooolding lists
use foldr and foldl
best to think of foldl and foldr nonrecursively [PIH] pp. 65 & 68
 foldl and foldr take a prefix binary function,
 a base value of recursion, and a list, in that order
 foldl :: (a > b > a) > a > [b] > a
 foldl associates from the left:
 +(+(+(+(0,1),2),3),4) = 10
 think of foldl as using the accumulator approach
ans5 = foldl (+) 0 [1,2,3,4]
 ((((0,1),2),3),4) = (((01)2)3)4 = 10
ans6 = foldl () 0 [1,2,3,4]
 foldr :: (a > b > b) > b > [a] > b
 foldr associates from the right:
 (1 :: (2 :: (3 :: [])))
 (1  (2  (3  (4  0)))) = 2
ans7 = foldr () 0 [1,2,3,4]
 for reasons of efficiency, use foldl
 rather than foldr when they produce the
 same result
sumlist = foldl (+) 0
 ref. [PIH] pp. 6566
length1 = foldr (\_ n > n+1) 0
 cons reversed
snoc x xs = xs ++ [x]
reverse6a [] = []
reverse6a (x:xs) = snoc x (reverse6a xs)
reverse6 = foldr snoc []
 ref. [PIH] p. 148
reverse7 = foldl (\xs x > x : xs) []
Putting it all together: higherorder functions
Use these concepts (higherorder functions)
to define a function string2int
which converts a string representation of an integer to the
corresponding integer:
Main> :type string2int
string2int :: [Char] > Int
Main> string2int "0"
0
Main> string2int "123"
123
Main> string2int "321"
321
Main> string2int "5643452"
5643452
Hint: only requires 2 lines of code, or only 1 if you use
a literal function (see below).
import Data.Char (ord)
char2int sumsofar initChar = (ord initChar)  (ord '0') + 10*sumsofar
string2int l = foldl char2int 0 l
string2int' = foldl (\r c > (ord c)  (ord '0') + 10*r) 0
char2int' initChar sumsofar = (ord initChar)  (ord '0') + 10*sumsofar
 not recommended, why? hint: two reasons
string2int'' s = foldr char2int' 0 (reverse s)
Overloading
contrast square function in Haskell with that in ML
square n = n*n
Main> :type square
square :: Num a => a > a
 the type of square is a 'qualified type'
 and Num is a 'type class'
Summary
(ref. [WFPM])
Higherorder functions (allows functions to be
glued together) and lazy evaluation (allows whole programs
to be glued together) are the glue which
allows us to combine program components together in creative ways to
produce concise, malleable, and reusable programs and, thereby
enables modular programming which makes programs easier to
debug, maintain, and reuse.
ML
fun ourmap f nil = nil
 ourmap f (x::xs) = (f x)::ourmap f xs;
fun square x = x*x;
ourmap square [1,2,3,4,5,6];
fun squarelist lon = map square lon;
squarelist [1,2,3,4,5,6];
vs.
val squarelist = map square;
Functional composition
ML's composition operator o
fun add3 x = x+3;
fun mult2 x = x*2;
val add3_then_mult2 = mult2 o add3;
val mult2_then_add3 = add3 o mult2;
add3_then_mult2 3;
(* val it = 12 : int *)
mult2_then_add3 3;
(* val it = 9 : int *)
val add3_then_mult2 = (op o) (mult2, add3);
(* op converts an infix operator to a prefix operator *)
(* be careful *)
(op *) (4, 5); (* doesn't work *)
(op * ) (4, 5); (* now it works *)
Fooooolding lists
(* foldl and foldr take a prefix binary function,
a base value of recursion, and a list, in that order *)
(* the standard ML foldl seems to have the wrong type!
foldl : ('a * 'b > 'b) > 'b > 'a list > 'b
foldl associates from the left (e.g.,
+(+(+(+(0,1),2),3),4) = 10)
think of foldl as using the accumulator approach *)
foldl (op +) 0 [1,2,3,4];
(* (4, (3, (2, (1,0)))) = 4(3(2(10))) = 2 *)
foldl (op ) 0 [1,2,3,4];
(* foldr : ('a * 'b > 'b) > 'b > 'a list > 'b
foldr associates from the right (e.g.,
(1 :: (2 :: (3 :: []))))
(1  (2  (3  (4  0)))) = ~2 *)
foldr (op ) 0 [1,2,3,4];
val sumlist = foldr (op +) 0;
Putting it all together: higherorder functions
 now we use these concepts to define our own implode function
implode (explode ("apple"));
(* val it = "apple" : string *)
val exploded = explode ("apple");
(* val exploded = [#"a",#"p",#"p",#"l",#"e"] : char list *)
val apple = implode ([#"a",#"p",#"p",#"l",#"e"]);
(* val apple = "apple" : string *)
(* first attempt at implementing our own version of implode *)
val combine x = foldr (op ^) #"";
why will this not work?
(* str converts from char to string *)
(* char list > string *)
val ourimplode = (foldr op ^ "") o (map str); (* this works *)
 converting a string representing an integer to an integer
(* example: 123 = (3+0) + (2*10) + (1*100) *)
fun char2int (c, v) = ord (c)  ord (#"0") + 10*v;
(* val char2int = fn : char * int > int *)
(* char2int (#"3", char2int (#"2", char2int (#"1", 0))); *)
foldl char2int 0 (explode ("123"));
(* val it = 123 : int *)
fun string2int s = foldl char2int 0 (explode s);
fun string2int1 s = foldl (fn (c, v) => ord (c)  ord (#"0") + 10*v) 0 (explode s);
References
[EMLP] 
J.D. Ullman.
Elements of ML Programming.
Prentice Hall, Upper Saddle River, NJ, Second edition, 1997. 
[PIH] 
G. Hutton.
Programming in Haskell.
Cambridge University Press, Cambridge, 2007.

