Partial application
In computer science, partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity. Given a function , we might fix (or 'bind') the first argument, producing a function of type . Evaluation of this function might be represented as . Note that the result of partial function application in this case is a function that takes two arguments. Partial application is sometimes incorrectly called currying, which is a related, but distinct concept.
Motivation
Intuitively, partial function application says "if you fix the first arguments of the function, you get a function of the remaining arguments". For example, if function div(x,y) = x/y, then div with the parameter x fixed at 1 is another function: div1(y) = div(1,y) = 1/y. This is the same as the function inv that returns the multiplicative inverse of its argument, defined by inv(y) = 1/y.
The practical motivation for partial application is that very often the functions obtained by supplying some but not all of the arguments to a function are useful; for example, many languages have a function or operator similar to plus_one
. Partial application makes it easy to define these functions, for example by creating a function that represents the addition operator with 1 bound as its first argument.
Implementations
In languages such as ML, Haskell and F#, functions are defined in curried form by default. Supplying fewer than the total number of arguments is referred to as partial application.
In languages with first-class functions one can define curry
, uncurry
and papply
to perform currying and partial application explicitly. This might incur a greater run-time overhead due to the creation of additional closures, while Haskell can use more efficient techniques.[1]
Scala implements optional partial application with placeholder, e.g. def add(x: Int, y: Int) = {x+y}; add(1, _: Int)
returns an incrementing function. Scala also support multiple parameter lists as currying, e.g. def add(x: Int)(y: Int) = {x+y}; add(1) _
.
Clojure implements partial application using the partial
function defined in its core library.[2]
The C++ standard library provides bind(function, args..)
to return a function object that is the result of partial application of the given arguments to the given function. Alternatively, lambda expressions can be used:
int f(int a, int b);
auto f_partial = [](int a) { return f(a, 123); };
assert(f_partial(456) == f(456, 123) );
In Java, MethodHandle.bindTo
partially applies a function to its first argument.[3]
Alternatively, since Java 8, lambdas can be used:
public static <A, B, R> Function<B, R> partialApply(BiFunction<A, B, R> biFunc, A value) {
return b -> biFunc.apply(value, b);
}
In Raku, the assuming
method creates a new function with fewer parameters.[4]
The Python standard library module functools
includes the partial
function, allowing positional and named argument bindings, returning a new function.[5]
In XQuery, an argument placeholder (?
) is used for each non-fixed argument in a partial function application.[6]
Definitions
In the simply-typed lambda calculus with function and product types (λ→,×) partial application, currying and uncurrying can be defined as:
papply
- (((a × b) → c) × a) → (b → c) = λ(f, x). λy. f (x, y)
curry
- ((a × b) → c) → (a → (b → c)) = λf. λx. λy. f (x, y)
uncurry
- (a → (b → c)) → ((a × b) → c) = λf. λ(x, y). f x y
Note that curry
papply
= curry
.
See also
References
- Marlow & Peyton Jones 2004
- "clojure/clojure, partial function". GitHub. Retrieved 2020-07-18.
- "MethodHandle (Java Platform SE 7)". docs.oracle.com. Retrieved 2018-09-12.
- "Method assuming". docs.perl6.org. Retrieved 2018-09-12.
- "10.2. functools — Higher-order functions and operations on callable objects — Python 3.7.0 documentation". docs.python.org. Retrieved 2018-09-12.
- "XQuery 3.1: An XML Query Language". www.w3.org. Retrieved 2018-09-12.
Further reading
- Simon Marlow and Simon Peyton Jones (2004, 2006). "Making a Fast Curry: Push/Enter vs. Eval/Apply for Higher-order Languages". ICFP '04 Proceedings of the ninth ACM SIGPLAN international conference on Functional programming.
- Benjamin C. Pierce et al. "Partial Application", "Digression: Currying". Software Foundations.
External links
- Partial function application on Rosetta code.
- Partial application at Haskell Wiki
- Constant applicative form at Haskell Wiki
- The dangers of being too partial