2010-08-11 14 views
17

Si tengo:¿Cómo obtengo (a, b) => c de a => b => c en Scala?

val f : A => B => C 

Esta es la abreviatura de:

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

¿Cómo consigo una función g con la firma:

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

(es decir)

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

en términos de f?

Respuesta

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

scala> Function.uncurried(f) 
res0: (Int, Int) => Int = <function2> 
+3

¿Es extraño que no haya un método 'no comprobado' en' FunctionN' en sí? –

+1

Para tener un método no cursado en la Función1, necesitaría limitar los objetivos aceptables para las funciones que devuelven funciones. Es decir, funciones con el tipo Function1 [A, Function1 [B, C]]. Eso probablemente podría hacerse con restricciones de tipo generalizadas, pero esas no estaban disponibles hasta Scala 2.8. –

13

La extensión de la respuesta de retonym, para lo completo

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) 

Las funciones converse para ambas operaciones también se proporcionan en el objeto de función, por lo que se podría escribir lo anterior al revés, si hubiese deseado

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 
9

Solo para completar la respuesta, aunque hay un método de biblioteca para hacer esto, también puede ser instructivo hacerlo a mano:

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> 

o, en general,

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

Similar a la respuesta de Rex Kerr pero más fácil de leer.

type A = String 
type B = Int 
type C = Boolean 

val f: A => B => C = s => i => s.toInt+i > 10 

val f1: (A, B) => C = f(_)(_) 
Cuestiones relacionadas