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?
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).
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With