我对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
那是怎么回事?我的直觉应该是什么?
答案 0 :(得分:10)
Scala尝试一次确定一个参数块的类型。如果添加其他参数并部分应用,则可以看到此内容:
def x[T](a: T, b: T)(c: T) = (a == b)
scala> x(1, "one") _
res0: Any => Boolean = <function1>
当然,Int
和String
都是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>