There are two key points about partial application. The first is syntactic/convenience -- some definitions become easier and shorter to read and write, as @jk mentioned. ( Check out Pointfree programming for more about how awesome this is! )
The second, as @telastyn mentioned, is about a model of functions and is not merely convenient. In the Haskell version, from which I'll get my examples because I'm not familiar with other languages with partial application, all functions take a single argument. Yes, even functions like:
(:) :: a -> [a] -> [a]
take a single argument; because of the associativity of the function type constructor ->
, the above is equivalent to:
(:) :: a -> ([a] -> [a])
which is a function that takes an a
and returns a function [a] -> [a]
.
This allows us to write functions like:
($) :: (a -> b) -> a -> b
which can apply any function to an argument of the appropriate type. Even crazy ones like:
f :: (t, t1) -> t -> t1 -> (t2 -> t3 -> (t, t1)) -> t2 -> t3 -> [(t, t1)]
f q r s t u v = q : (r, s) : [t u v]
f' :: () -> Char -> (t2 -> t3 -> ((), Char)) -> t2 -> t3 -> [((), Char)]
f' = f $ ((), 'a') -- <== works fine
Okay, so that was a contrived example. But a more useful one involves the Applicative type class, which includes this method:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
As you can see, the type is identical similar to $
if you take away the Applicative f
bit, and in fact, this class describes function application in a context. So instead of normal function application:
ghci> map (+3) [1..5]
[4,5,6,7,8]
We can apply functions in an Applicative context; for example, in the Maybe context in which something may be either present or missing:
ghci> Just map <*> Just (+3) <*> Just [1..5]
Just [4,5,6,7,8]
ghci> Just map <*> Nothing <*> Just [1..5]
Nothing
Now the really cool part is that the Applicative type class doesn't mention anything about functions of more than one argument -- nevertheless, it can deal with them, even functions of 6 arguments like f
:
fA' :: Maybe (() -> Char -> (t2 -> t3 -> ((), Char)) -> t2 -> t3 -> [((), Char)])
fA' = Just f <*> Just ((), 'a')
As far as I know, the Applicative type class in its general form would not be possible without some conception of partial application. (To any programming experts out there -- please correct me if I'm wrong!) Of course, if your language lacks partial application, you could build it in in some form, but ... it's just not the same, is it? :)
f x y = x + y
means thatf
is a function that takes one int parameter. The result off x
(f
applied tox
) is a function that takes one int parameter. The resultf x y
(or(f x) y
, i.e.f x
applied toy
) is an expression that takes no input parameters and is evaluated by reducingx + y
.