Scala中的多个较低类型边界

kas*_*ens 12 type-systems jvm scala

我注意到,如果不可能设置多个下限(因此它可能是最低常见超类型的迭代器),tuple.productIterator总会返回一个Iterator[Any]想知道的问题.

我尝试了一下搜索,但只发现了这个问题的多个上界.

这是我对如何定义迭代器类型的测试:

def f[A,B](a:A, b:B) = List(a,b)
// return type is List[Any]

def f[A,B, T >: A "and" T >: B](a:A, b:B) = List[T](a,b)
// doesn't compile, but
//  f(1, true) should give a List[AnyVal] and
//  f("x", "y") a List[String]
Run Code Online (Sandbox Code Playgroud)

这是JVM的限制吗?


编辑: 这是一个稍大的例子,当在方法中定义T时,使用IttayD方法似乎无法解决这个问题:

class Foo[A, B](a: A, b: B) {
  def f[T >: A] = List[T](a) // works
  def g[T >: A "and" T >: B] = List[T](a) // doesn't work
}
Run Code Online (Sandbox Code Playgroud)

Jea*_*let 10

对于简单的情况,其中AB编译器同时绑定T,IttayD的答案工作正常:

def f[T, A <: T,B <: T](a:A, b:B) = List[T](a,b)
Run Code Online (Sandbox Code Playgroud)

当你的示例中已经绑定A并且B已经绑定时class Foo[A, B],需要引入临时虚拟变量以使编译器完成此任务:

class Foo[A, B](a: A, b: B) {
  def g[T, A1 >: A <: T, B1 >: B <: T] = List[T](a: A1, b: B1)
}
Run Code Online (Sandbox Code Playgroud)

(为了清楚起见:A1 >: A <: T意味着类型A1必须的超类型A和子类型T,并不算A是两者的亚型A1T).

A1并且B1这里的唯一目的是推断出正确的类型T.如果编译器来推断他们,他们会下定决心,A1 = AB1 = B,然后T作为最具体类型,是两者的超AB.

但是,编译器没有意识到的一件事是,通过传递性,我们有两个T >: AT >: B,它直接来自关于A1和的约束B1.我们需要帮助解决类型问题.

现在,Product#productIterator不能使用这种技术,因为它在一个地方的定义,我们甚至不知道AB,或确实有多少类型的参数中有具体子类.