Introduction to Programming Languages/Partial Application

Partial Application


In many programming languages, most notably in members of the functional paradigm such as ML and Haskell, every function takes only one argument as an input parameter. For instance, a ML function such as add(x, y) does not receive two parameters, x and y, as one could, at first think. It receives one parameter: the tuple (x, y):

- fun add(x, y) = x + y;
val add = fn : int * int -> int

- val t = (2, 3);
val t = (2,3) : int * int

- add t;
val it = 5 : int

In order to give developers the illusion that a function takes several parameters, these languages resort to a technique called currying. A curried function such as f(x)(y) takes an argument x, and returns a new function that takes another argument y, and might use the value of x inside its body. As an example, the function below is the curried version of the previous implementation of add:

- fun add_curry x y = x + y;
val add_curry = fn : int -> int -> int

- add_curry 2 3;
val it = 5 : int

Usually we do not need to pass all the sequence of arguments expected by a curried function. If we pass only the prefix of this sequence of arguments, then we have a Partial Application. The result of a partial application is normally implemented as a closure. For instance, below we are using our add_curry function as a function factory:

- fun add_curry a b = a + b;
val add_curry = fn : int -> int -> int

- val inc = add_curry 1;
val inc = fn : int -> int

- inc 2;
val it = 3 : int

- val sum2 = add_curry 2;
val sum2 = fn : int -> int

- sum2 2;
val it = 4 : int

Closures · Noticeable High-Order Functions