Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic type unification: multiple parameters (T,T) vs. multiple parameter lists (T)(T)?

Tags:

generics

scala

I'm a bit confused by the difference in type-checking between curried and uncurried generic functions:

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

My intuition was that both x(1, "one") and y(1)("one") should give type errors, but I was wrong:

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")
                   ^

At first I thought there was some sort of implicit casting going on, but that didn't seem to be the case:

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

So what's going on? What should my intuition be?

like image 886
rampion Avatar asked Jan 05 '12 20:01

rampion


2 Answers

Scala tries to determine types one parameter block at a time. You can see this if you add another parameter and partially apply:

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

Of course, both Int and String are Any (and == is defined on Any).

Type parameters which are not used in an earlier block remain free to be used in a later block:

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

You can also use earlier blocks as default values in later blocks!

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

Thus, distributing your parameters amongst multiple parameter blocks has consequences both for type inference and for defaulting (and for partial application).

like image 118
Rex Kerr Avatar answered Oct 06 '22 01:10

Rex Kerr


I think that in the first case it is upcasting (downcasting?) both arguments such that T:Any. In the second, it is currying for Int, and then failing on the String.

This seems to bear me out:

scala> y(1)_
res1: Int => Boolean = <function1>
like image 25
Chris Shain Avatar answered Oct 06 '22 00:10

Chris Shain