Scala 中的多个类型下限

发布于 2024-11-09 16:13:27 字数 856 浏览 0 评论 0原文

我注意到 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]

这是 JVM 的限制吗?


Edit: Here's a slightly bigger example which doesn't seem to be solvable using IttayD approach when T should be defined in the method:

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
}

I noticed that tuple.productIterator always returns an Iterator[Any] an wondered if it's not possible to set multiple lower bounds (so it could be an Iterator of the lowest common super type).

I tried and searched a bit, but only found this question for multiple upper bounds.

This is my test on how to define the the type of the iterator:

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]

Is this a limitation of the JVM?


Edit:
Here's a slightly bigger example which doesn't seem to be solvable using IttayD approach when T should be defined in the method:

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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

停顿的约定 2024-11-16 16:13:27

对于 ABT 同时被编译器绑定的简单情况,IttayD 的答案工作正常:

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)
}

(For为了清楚起见: A1 >: A <: T 表示类型 A1 必须是 A 的超类型和 A 的子类型code>T,而不是那个AA1T 的子类型。)

A1B1< /code> 在这里的唯一目的是推断 T 的正确类型。如果编译器必须推断它们,它们将解析为 A1 = AB1 = B,然后将 T 作为最具体的类型是 AB 的超类。

然而,编译器没有意识到的一件事是,通过传递性,我们同时拥有 T >: AT >: B,它直接跟随来自关于 A1B1 的约束。我们需要帮助解决类型归属问题。

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

For the simple case where A and B are bound by the compiler as the same time as T, IttayD's answer works fine:

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

When A and B are already bound as in your class Foo[A, B] example, you need to introduce temporary dummy variables to have the compiler do this job:

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

(For the sake of clarity: A1 >: A <: T means that type A1 must be a supertype of A and a subtype of T, and not that A is a subtype of both A1 and T.)

A1 and B1 are here for the sole purpose of inferring a correct type for T. If the compiler has to infer them, they will resolve to A1 = A and B1 = B, and then T as the most specific type which is a superclass of both A and B.

One thing that the compiler doesn't realize, though, is that, by transitivity, we have both T >: A and T >: B, which follows directly from the constraints with respect to A1 and B1. We need to help out with the type ascriptions.

Now, Product#productIterator could not use this technique, as it's defined in a place where we don't even know A and B, or indeed how many type parameters there are in the concrete subclass.

柠檬色的秋千 2024-11-16 16:13:27

听起来你需要的是一个 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)

It sounds like what you need is an HList: http://apocalisp.wordpress.com/2010/07/06/type-level-programming-in-scala-part-6a-heterogeneous-list%C2%A0basics/

To answer the specific question:

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文