Question

Everywhere I look, I see the terms multiple parameter lists and currying used interchangably. I see it in dozens of stackoverflow questions, and even on scala-lang.org. This page, for example, has the title "Currying". And the first sentence? "Methods may define multiple parameter lists."

And yet some very knowledgeable people get annoyed when they see multiple parameter lists and currying equated. I posted an answer to this question but then deleted it when I saw Randall Schulz's comment because I was afraid I might be inadvertently spreading misinformation. My understanding was that a function with multiple parameter lists is necessarily a curried function, but that function currying can be achieved in other ways as well (the top answer to this question lists four ways), but I'm not sure that's the whole story. I want to really understand the distinction.

I know there are a lot of very similar questions to this one on stackoverflow, but I haven't found one that precisely spells out the difference. What do I need to understand about multiple parameter lists and currying in order to speak accurately about them?

Was it helpful?

Solution

I hope you don't mind if I start with a Haskell example, since Haskell is a vastly simpler language than Scala. In Haskell all functions are functions in the mathematical sense—they take one argument and return one value. Haskell also has tuples, and you can write a function that looks a little like it takes multiple parameters, as a function from a tuple to whatever. For example:

Prelude> let add = (\(x, y) -> x + y) :: (Int, Int) -> Int
Prelude> add (1, 2)
3

Now we can curry this function to get a function with type Int -> Int -> Int instead of (Int, Int) -> Int:

Prelude> let curriedAdd = curry add

This allows us to partially apply the function, for example:

Prelude> let add3 = curriedAdd 3
Prelude> add3 1
4

So we have a nice clean definition of currying—it's a function that takes a function with a tuple (specifically a pair) for an argument and returns a function that takes as an argument the first type in the pair and returns a function from the second type in the pair to the original return type. Which is just a wordy way to say this:

Prelude> :t curry
curry :: ((a, b) -> c) -> a -> b -> c

Okay, now for Scala.

In Scala you can also have functions that take a tuple argument. Scala also has "functions" that take more than one argument (Function2 and up). These are (confusingly) different kinds of animals.

Scala also has methods, which are different from functions (although they can be converted to functions more or less automatically via eta expansion). Methods can have multiple parameters, or tuple parameters, or multiple parameter lists.

So what does it mean to say we're currying something in this context?

Most literally, currying is something you do with a Function2 (and up):

scala> val add: Function2[Int, Int, Int] = (x: Int, y: Int) => x + y
add: (Int, Int) => Int = <function2>

scala> val curriedAdd = add.curried
curriedAdd: Int => (Int => Int) = <function1>

scala> val add3 = curriedAdd(3)
add3: Int => Int = <function1>

This is about the same as what we saw in the Haskell case, except that we're currying a function with multiple arguments, which is something that doesn't properly exist in Haskell.

Now I'm pretty sure this is the only context in which the word curry actually appears in the Scala standard library (not counting the accompanying uncurried on the Function companion object), but given the enormous mess that Scala makes of the idea of methods, functions, etc. (don't get me wrong—I love Scala, but this part of the language is a complete disaster), it seems pretty reasonable to me to apply the word in the following context as well:

def add(x: Int, y: Int) = x + y
def curriedAdd(x: Int)(y: Int) = add(x, y)

Here we've turned a method that takes two parameters into a method with multiple parameter lists—each of which only takes a single parameter (this last part is important).

And in fact the language specification also uses the term in this context, describing the following as "a single, curried function definition":

def func(x: Int)
        (y: Int) = x + y

(Which is of course confusing as hell, since this is a method, not a function.)

So to sum up: multiple parameter lists are one way to implement currying in Scala, but not all methods with multiple parameter lists are curried—only ones where each parameter list has a single parameter. And all the terminology is pretty mushy, anyway, so don't worry too much about getting it right.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top