views:

169

answers:

3

If I have:

val f : A => B => C

This is shorthand for:

val f : Function1[A, Function1[B, C]]

How do I get a function g with the signature:

val g : (A, B) => C = error("todo")

(i.e.)

val g : Function2[A, B, C] //or possibly
val g : Function1[(A, B), C]

in terms of f?

+12  A: 
scala> val f : Int => Int => Int = a => b => a + b
f: (Int) => (Int) => Int = <function1>

scala> Function.uncurried(f)
res0: (Int, Int) => Int = <function2>
retronym
Odd that there is no `uncurried` method on `FunctionN` itself?
oxbow_lakes
To have an uncurried method on Function1, you would need to limit the acceptable targets of it to functions that return functions. That is to say functions with type Function1[A, Function1[B, C]]. That could probably be done with generalized type constraints, but those weren't available until Scala 2.8.
Dave Griffith
+6  A: 

Extending retonym's answer, for completeness

val f : Int => Int => Int = a => b => a + b
val g: (Int, Int) => Int = Function.uncurried(f)
val h: ((Int, Int)) => Int = Function.tupled(g)

The converse functions for both of these operations are also provided on the Function object, so you could write the above backwards, if you wished

val h: ((Int, Int)) => Int =  x =>(x._1 + x._2)
val g: (Int, Int) => Int = Function.untupled(h)
val f : Int => Int => Int = g.curried  //Function.curried(g) would also work, but is deprecated. Wierd
Dave Griffith
+4  A: 

Just to round out the answer, although there is a library method to do this, it may also be instructive to do it by hand:

scala> val f = (i: Int) => ((s: String) => i*s.length)
f: (Int) => (String) => Int = <function1>

scala> val g = (i: Int, s: String) => f(i)(s)
g: (Int, String) => Int = <function2>

Or in general,

def uncurry[A,B,C](f: A=>B=>C): (A,B)=>C = {
  (a: A, b: B) => f(a)(b)
}
Rex Kerr