Both currying and partial application imply that a language supports higher-order functions--that is, passing functions around as data--since they'd be useless otherwise, and using higher-order functions, both currying and partial application can be implemented manually.
Aside from the above, they're separate ideas.
Would you say that having a while
loop "enables" for
or foreach
loops? In some sense that's true, but it tells you nothing useful about the loops.
Partial application means exactly what it says; you apply a function to some of its arguments, producing a specialized version that only needs the remaining arguments. This can be done with or without currying the function, perhaps using a wrapper function to juggle arguments around like apply_foo_to_baz(baz) = ((bar, quux) => foo(bar, baz, quux));
, if you'll pardon the pseudocode.
Currying means converting a function that takes multiple parameters like foo1(bar, baz, quux);
into one that is applied to a single argument at a time, like foo2(bar)(baz)(quux);
. Applying foo2
to fewer arguments is technically not partial application, because the function only takes one argument. Knowing that foo2
is a curried version of foo1
, we can think of foo2(bar)
as being a partially-applied form of foo1
, but there's nothing about curried functions in general that make them "partially applied" given any particular number of arguments.
As far as Haskell is concerned, functions defined in the usual way are actually curried by default (which is fitting, since both are named after the same person). In fact, it's actually a bit tricky to usefully define what "partial application" means in Haskell without relying on implementation details.