11

I have several questions related curried function. Here I ask them one-by-one

1) http://twitter.github.com/scala_school/basics.html gives an example of curried function -- I thought it's a function definition, but actually it's not. The REPL does not recognize this as a valid statement at all.

multiplyThenFilter { m: Int =>   m * 2 } { n: Int =>   n < 5}

2) Why can't we define a function from partially parameterized method? i.e., what's wrong with the following definition?

scala> def multiply(m: Int, n: Int): Int = m * n
multiply: (m: Int, n: Int)Int

scala> val timesTwo = multiply(2,_)
<console>:11: error: missing parameter type for expanded function ((x$1) => multiply(2, x$1))
       val timesTwo = multiply(2,_)
                                 ^

3) Why can't we make a partially parameterized function curried? i.e., what's wrong with the following definition?

scala> (multiply(_,_)).curried
  res13: Int => (Int => Int) = <function1>  // THIS IS OK

scala> (multiply(20,_)).curried
<console>:12: error: missing parameter type for expanded function ((x$1) => multiply(20, x$1))
              (multiply(20,_)).curried
                           ^
kiritsuku
  • 52,967
  • 18
  • 114
  • 136
chen
  • 4,302
  • 6
  • 41
  • 70
  • 1) It is not valid, cause it must be declared first. For example, like that: `def multiplyThenFilter(a: Int => Int)( b: Int => Boolean) = { List(1,2,3,4).map(a).filter(b) }` – om-nom-nom Jun 10 '12 at 19:12
  • 1) The multiplyThenFilter is gone now. You weren't the only person confused by it :-) – Larry Hosken Aug 14 '12 at 15:40

1 Answers1

12

Question 1

The Scala School example is confusing—it's definitely not a definition. There's an issue open for it on GitHub, so maybe it's a bug. You can imagine a reasonable definition might look like this:

def multiplyThenFilter(f: Int => Int)(p: Int => Boolean): Int => Option[Int] = {
  i =>
    val j = f(i)
    if (p(j)) Some(j) else None
}

(Or, equivalently, f andThen (Some(_) filter p).)

Then the example would be a function that doubles its input and returns the result in a Some if it's less than 5, and a None otherwise. But nobody knows exactly what the author intended until there's a response to that issue.


Question 2

The reason that your timesTwo doesn't work is just that the Scala compiler doesn't support that kind of type inference—see this question and my answer there for a bit of related detail. You'll need to go with one of the following:

def multiply(m: Int, n: Int): Int = m * n    
val timesTwo = multiply(2, _: Int)

def multiply(m: Int)(n: Int): Int = m * n    
val timesTwo = multiply(2) _

I.e., if you want type inference here you'll need to use multiple parameter lists. Otherwise you have to help the compiler out with the type.


Question 3

For your third question, assume we've got the following to avoid the issue in your second question:

val timesTwo = multiply(2, _: Int)

This is a Function1, which just doesn't have a curried method—you need a Function2 (or Function3, etc.) for that.

It just doesn't make sense to talk about currying a function with a single argument. Currying takes a function with multiple arguments and gives you a function taking a single argument that returns another function (which itself possibly takes a single argument and returns another function, etc.).

Community
  • 1
  • 1
Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • are the two functions 'timesTwo' defined in "val timesTwo = multiply(2, _: Int)" and "val timesTwo = multiply(2) _" in your answer to Question 2 with same type? – chen Jun 10 '12 at 21:37
  • Yes, they're both `Int => Int` (or equivalently `Function1[Int, Int]`). – Travis Brown Jun 10 '12 at 21:44