为什么Scala在嵌套类型参数时不能完全推断类型参数?

Tom*_*bel 13 scala

请考虑以下Scala代码:

abstract class A
abstract class B[T <: A]
class ConcreteA extends A
class ConcreteB extends B[ConcreteA]

class Example[U <: B[T], T <: A]( resolver: U )
object Test {
    new Example( new ConcreteB )
}
Run Code Online (Sandbox Code Playgroud)

最后一行new Example( new ConcreteB )无法编译,出现以下错误:

错误:推断类型参数[ConcreteB,Nothing]不符合类Example的类型参数bounds [U <:B [T],T <:A]

但是ConcreteB有解决U T的所有必要数据.我在这里缺少什么?

Kip*_*ros 10

(另请参阅两个相关问题:Scala无法推断出正确的类型参数,并且Scala中的Nothing类型为impued)

它看起来像Scala的类型推断的限制,这是有意没有规定的.作为变通,你可以通过获得推理T类型成员B,而不是参数,

abstract class A
abstract class B { type T <: A }
class ConcreteA extends A
class ConcreteB extends B { type T = ConcreteA }
class Example[U <: B]( resolver: U )
object Test {
    new Example( new ConcreteB )
}
Run Code Online (Sandbox Code Playgroud)

当使用类型成员时,知道它们可以使用细化表示为类型参数是有用的,如在Miles Sabin的回答中:为什么带有类型投影的循环引用是非法的?

在Jean-Philippe Pellet对相关问题的回答中,通过使类型参数更高的类型来辅助类型推断.如果你引入一个额外的类型参数ConcreteB,然后键入推断可以工作,

abstract class A
abstract class B[T <: A]
class ConcreteA extends A
class ConcreteB[T <: A] extends B[T]
class Example[T <: A, U[T0 <: A] <: B[T0]]( resolver: U[T] )
object Test {
  new Example( new ConcreteB[ConcreteA] )
}
Run Code Online (Sandbox Code Playgroud)

Scala 2.9给出了下面的神秘错误消息,但Miles Sabin指出这是一个将修复为2.9.1的错误

<console>:15: error: kinds of the type arguments (ConcreteA,ConcreteB[T0]) do not conform to the expected kinds of the type parameters (type T,type U) in class Example.
ConcreteB[T0]'s type parameters do not match type U's expected parameters: class ConcreteB has one type parameter, but type U has one
         new Example( new ConcreteB[ConcreteA] )
             ^
Run Code Online (Sandbox Code Playgroud)


Mil*_*bin 10

基普顿与他的高级解决方案接近.不幸的是,他绊倒了Scala <2.9.1.RC1中的一个错误.以下工作与2.9.1.RC1和trunk一样,

Welcome to Scala version 2.9.1.RC1 (Java HotSpot(TM) Server VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> abstract class A
defined class A

scala> abstract class B[T <: A]
defined class B

scala> class ConcreteA extends A
defined class ConcreteA

scala> class ConcreteB[T <: A] extends B[T]
defined class ConcreteB

scala> class Example[T <: A, U[X <: A] <: B[X]](resolver: U[T])
defined class Example

scala> new Example(new ConcreteB[ConcreteA])
res0: Example[ConcreteA,ConcreteB] = Example@ec48e7
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

6488 次

最近记录:

11 年,6 月 前