“Currying” or “partial application”?
Consider this piece of the Haskell Standard Prelude:
-- curry converts an uncurried function to a curried function;
-- uncurry converts a curried function to a function on pairs.
curry :: ((a, b) -> c) -> a -> b -> c
curry f x y = f (x, y)
uncurry :: (a -> b -> c) -> ((a, b) -> c)
uncurry f p = f (fst p) (snd p)
This is formally, pedantically correct. Surprisingly, it's also useful from time to time, mostly when composing functions that return pairs. But since most Haskell functions are already curried, it's not as heavily used as other Prelude functions such as flip
.
Dylan has a different idea. It uses curry(\+, 1)
to mean (λ x → 1 + x)
. The same thing (partial application as a function) has been done in Python and C++, but without the misleading name.
Some people don't like this. They consider the Dylan usage a reckless abuse of words.
Early versions of SRFI-26 proposed calling partial application curry
, to which Dave Mason said:
It would also be really nice at ICFP or other places where Schemers and Haskell types get together if the Schemers don't look like complete idiots when they misuse the term `curry' because of this SRFI's poor choice of name.
I used to think this was silly. Curried functions exist to make partial application easy, and other tools for partial application accomplish the same goal in a different way. (The practical difference is that they specify partial application at the call site, while curried functions specify it at the function's definition.) Why use two different words? Is there ever a time when the distinction matters?
There is: when you're designing a language, you have to think about these things. While considering a partial application feature in my pet lisp, I found myself needing to talk about several terse ways of obtaining partial application. Should I use curried functions? A currying function? A partial-apply
function? A macro like op
? I needed to talk about all of these at once.
But most users don't, and it's futile to try to force people to make distinctions they don't care about. They just want partial application, and if they get it from a function like Dylan's, they will inevitably adopt the short, distinctive name curry
for it. The abuse of the term might be a problem in other contexts, but in a language without curried functions, it is not likely to confuse.
And since partial application is so often useful, I did decide to include it in my pet lisp. I used op
, and built it into the Form Without A Name. That way it doesn't require a name of its own, so the unwieldiness of “partial application” is not a big problem. Which is a good thing, because I use it a lot. Terse partial application makes functional programming easier, which means it is used more often than its lambda
equivalent. I'm glad I went to the trouble of adding it.
And I won't be upset when users call it “currying”.
> The same thing has been done in Python
ReplyDeleteWrong, the Python equivalent is correctly named partial, part of the functools module. It's not named curry, because discussions on the subject on the ML lead to the conclusion that using proper terms for existing concepts instead of mangled different (even if related concepts) was not a good idea.
In the Boost C++ library that facility is named bind, not curry. The documentation does not refer to it as a currying operation (nor as partial application).
ReplyDeleteSorry about that. I meant that the same feature (partial application as a function) has been done in Python and C++, not the same misnaming. I'll fix the text.
ReplyDeleteIn case it wasn't clear, I don't think calling partial application "curry" is a good idea. But it's mostly harmless, and it's an unsurprising metonymy, so I don't think it's worth worrying about.