2012-01-05 25 views
5

yo soy un poco confundido por la diferencia en el tipo de verificación entre los curry y uncurried funciones genéricas:Unificación de tipo genérico: parámetros múltiples (T, T) frente a listas de parámetros múltiples (T) (T)?

scala> def x[T](a: T, b: T) = (a == b) 
x: [T](a: T, b: T)Boolean 
scala> def y[T](a: T)(b: T) = (a == b) 
y: [T](a: T)(b: T)Boolean 

Mi intuición era que tanto x(1, "one") y y(1)("one") debe dar errores de tipo, pero estaba equivocado:

scala> x(1, "one") 
res71: Boolean = false 
scala> y(1)("one") 
<console>:9: error: type mismatch; 
found : java.lang.String("one") 
required: Int 
       y(1)("one") 
       ^

al principio pensé que había algún tipo de conversión implícita pasando, pero eso no parece ser el caso:

scala> x(1 :Int, "one" :String) 
res73: Boolean = false 

Entonces, ¿qué está pasando? ¿Cuál debería ser mi intuición?

+0

He visto un duplicado de esto hace mucho tiempo. También creo que este caso [casi] exacto está documentado en el SLS. –

+0

Ahí vamos. He actualizado el título con el importante término "listas de parámetros múltiples", que se analiza en el SLS :) –

Respuesta

9

Creo que en el primer caso se trata de la difusión ascendente (downcasting?) Ambos argumentos de modo que T: Any. En el segundo, está currying para Int, y luego falla en el String.

Esto me parece confirmar:

scala> y(1)_ 
res1: Int => Boolean = <function1> 
+0

Ok, parece probable, dado que 'y (1: Cualquiera) (" hello ")' devuelve 'falso'. – rampion

+0

Vea mi edición para obtener más evidencia de esto –

+0

Como una interesante nota al margen, esta pregunta parece invocar la afirmación hecha aquí: http://www.scala-lang.org/node/262 que "entonces f (x) (y) yg (x, y) se compilan exactamente en el mismo código ". –

10

Scala intenta determinar los tipos de un solo bloque de parámetros a la vez. Esto se puede ver si se agrega otro parámetro y parcialmente aplicable:

def x[T](a: T, b: T)(c: T) = (a == b) 
scala> x(1, "one") _ 
res0: Any => Boolean = <function1> 

Por supuesto, tanto Int y se String (se define y == en Any) Any.

parámetros de tipo que no se utilizan en un bloque anterior que permanezcan libres para ser utilizado en un bloque más adelante:

def y[T,U](a: T)(b: U)(c: (T,U)) = (a == b) 
scala> y(1)("one") 
res1: (Int, java.lang.String) => Boolean = <function1> 

También puede utilizar los bloques anteriores como valores por defecto en los bloques posteriores!

def z[T,U](a: T)(b: U)(c: (T,U) = (a,b)) = (c._1 == c._2) 
scala> z(1)("one")() 
res2: Boolean = false 

Por lo tanto, la distribución de sus parámetros entre varios bloques de parámetros tiene consecuencias tanto para la inferencia de tipos y por incumplimiento (y para la aplicación parcial).

Cuestiones relacionadas