Currying
What is currying?
Currying is the technique of expressing a function taking multiple arguments as nested functions, each taking a single argument. A curried function returns another function as its result.
Consider the string concatenation operator (^):
(^)
(* : string -> string -> string = <fun> *)
The type string -> string -> string means “a function that takes a string and returns a function from string to string”. Compare with an uncurried version using pairs:
| Curried | Uncurried |
|---|---|
string -> string -> string | string * string -> string |
| Takes one string, returns a function | Takes a pair of strings, returns a string |
| Allows partial application | Must supply both arguments together |
Defining curried functions
A curried function uses nested fun-notation:
let prefix = fun a -> fun b -> a ^ b
(* val prefix : string -> string -> string = <fun> *)
Applying this function to one argument yields another function:
let promote = prefix "Senior "
(* val promote : string -> string = <fun> *)
promote "Professor"
(* : string = "Senior Professor" *)
Promotion via partial application
Supplying the first argument of a curried function is called partial application. The resulting function has the first argument “fixed” and awaits the remaining arguments. This is sometimes called promotion: the function prefix applied to "Senior " promotes, yielding promote.
Mathematical intuition: the function x^y with y = 2 gives squaring; with y = 3 gives cubing; with y = 1 gives the identity function. Each is obtained by fixing the second argument.
Nesting of fun
The curried form nests fun expressions:
fun a -> fun b -> E
is read as: a function that takes a, and returns a function that takes b and computes E. In OCaml, -> associates to the right, so the type string -> string -> string means string -> (string -> string). Application associates to the left, so prefix "Senior " "Professor" means (prefix "Senior ") "Professor".