请考虑以下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 )
}
最后一行 new Example( new ConcreteB )
无法编译,并出现以下错误:
错误:推断类型参数[ConcreteB,Nothing]不符合类Example的类型参数bounds [U <:B [T],T <:A]
但 ConcreteB
拥有解决U和T的所有必要数据 . 我在这里缺少什么?
3 回答
基普顿与他的高级解决方案接近 . 不幸的是,他绊倒了Scala <2.9.1.RC1中的一个错误 . 以下工作与2.9.1.RC1和trunk一样,
(另见两个相关问题:Scala fails to infer the right type arguments和Type infered to Nothing in Scala)
它看起来像是Scala的限制's type inference, which is intentionally not spec' ed . 作为解决方法,您可以通过使
T
成为B
的类型成员而不是参数来进行推理,当使用类型成员时,'s useful to know that they can be surfaced as type parameters using refinement, as in Miles Sabin' s回答:Why is this cyclic reference with a type projection illegal?
在Jean-Philippe Pellet对a related question的回答中,通过使类型参数更高的类型来辅助类型推断 . 如果在
ConcreteB
中引入了一个额外的类型参数,那么类型推断可以工作,Scala 2.9给出了下面的神秘错误消息,但Miles Sabin指出这是一个将修复为2.9.1的错误
为了自己的学习,我在GitHub上创作了a document of type inference workarounds .
我发现一些有用的简单规则是:
Type parameters of type parameters cannot be inferred: Scala类型推断仅查看参数列表中指定的类型(不要与类型参数列表混淆) .
Previous parameters are not used to infer future parameters: 类型信息仅流经参数列表,而不是参数 .
但是,在这个特定的例子中,类型成员是前进的方向(感谢@Kipton Barros!)