通用类型统一:多个参数(T,T)与多个参数列表(T)(T)?

时间:2012-01-05 20:37:59

标签: generics scala

我对curried和uncurried通用函数之间的类型检查的差异感到有点困惑:

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

我的直觉是x(1, "one")y(1)("one")都应该给出类型错误,但我错了:

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

起初我以为有某种隐式演员正在进行,但情况似乎并非如此:

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

那是怎么回事?我的直觉应该是什么?

2 个答案:

答案 0 :(得分:10)

Scala尝试一次确定一个参数块的类型。如果添加其他参数并部分应用,则可以看到此内容:

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

当然,IntString都是Any==上定义了Any

以前的块中未使用的类型参数可以在以后的块中自由使用:

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

您也可以在以后的块中使用较早的块作为默认值!

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

因此,在多个参数块之间分配参数会对类型推断和默认(以及部分应用)产生影响。

答案 1 :(得分:9)

我认为在第一种情况下它是向上转换(向下转换?)两个参数,如T:Any。在第二个中,它正在为Int进行currying,然后在String上失败。

这似乎让我感到害怕:

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