Scala中的多个较低类型边界

时间:2011-05-24 23:23:27

标签: scala jvm type-systems

我注意到tuple.productIterator总是返回一个Iterator[Any],如果不可能设置多个下限(那么它可能是最低常见超类型的迭代器)。

我尝试了一下,但只找到了this多个上限的问题。

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

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]

这是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
}

2 个答案:

答案 0 :(得分:10)

对于编译器与A同时绑定BT的简单情况,IttayD's answer工作正常:

def f[T, A <: T,B <: T](a:A, b:B) = List[T](a,b)

AB已经绑定在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)
}

(为了清楚起见,A1 >: A <: T表示类型A1必须是A的超类型和T的子类型,而不是A {1}}是A1T的子类型。)

A1B1仅用于推断T的正确类型。如果编译器必须推断它们,它们将解析为A1 = AB1 = B,然后T作为最具体的类型,它是A和{{的超类1}}。

编译器没有意识到的一件事是,通过传递性,我们同时拥有BT >: A,它们直接来自T >: B的约束。和A1。我们需要帮助解决类型问题。

现在,B1无法使用此技术,因为它在我们甚至不知道Product#productIteratorA的地方定义,或者实际上有多少类型参数具体的子类。

答案 1 :(得分:4)

听起来你需要的是一个HList:http://apocalisp.wordpress.com/2010/07/06/type-level-programming-in-scala-part-6a-heterogeneous-list%C2%A0basics/

回答具体问题:

scala> def f[T, A <: T,B <: T](a:A, b:B) = List[T](a,b)
f: [T, A <: T, B <: T](a: A, b: B)List[T]

scala> f(1, true)
res0: List[AnyVal] = List(1, true)

scala> f("x", "y")
res1: List[java.lang.String] = List(x, y)