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

ram*_*ion 5 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
Run Code Online (Sandbox Code Playgroud)

我的直觉是,这两个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")
                   ^
Run Code Online (Sandbox Code Playgroud)

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

scala> x(1 :Int, "one" :String)
res73: Boolean = false
Run Code Online (Sandbox Code Playgroud)

发生什么了?我的直觉应该是什么?

Rex*_*err 10

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

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

当然,这两个IntStringAny(并且==被限定在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>
Run Code Online (Sandbox Code Playgroud)

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

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

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


Chr*_*ain 9

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

这似乎让我感到:

scala> y(1)_
res1: Int => Boolean = <function1>
Run Code Online (Sandbox Code Playgroud)