有时Scala无法推断出类型。这里的目标是了解原因并尝试帮助Scala做更好的推理。
用一个简单的例子可以更好地解释这个问题:
trait A
trait B
class G[Ao <: A, Bo <: B](a: Ao, b: Bo)
// This is my "complex" class with 3 type parameters
class X[Ao <: A, Bo <: B, Go <: G[Ao,Bo]](a: Ao, b: Bo, g: Go)
val a = new A{}
val b = new B{}
val g = new G(a,b)
此处下面的OO类型是完美推断:
class OO extends X(a,b,g) // Type of X[A,B,G[A,B]]
但是,如果我们将其中一个参数更改为一个选项(或任何集合),并且我们提供一个空集合(或None),则推理不起作用。
case class X[Ao <: A, Bo <: B, Go <: G[Ao,Bo]](a: Ao, b: List[Bo], g: Go)
class OO extends X(a,List(),g)
<console>:XX: error: inferred type arguments [A,Nothing,G[A,B]] do not conform to class X's type parameter bounds [Ao <: A,Bo <: B,Go <: G[Ao,Bo]]
class OO extends X(a,List(),g)
^
<console>:XX: error: type mismatch;
found : A
required: Ao
class OO extends X(a,List(),g)
^
<console>:XX: error: type mismatch;
found : G[A,B]
required: Go
class OO extends X(a,List(),g)
这可以通过显式传递OO的所有参数来修复:
class OO extends X[A,B,G[A,B]](a,List(),g)
问题是,G已经有了它的类型,从X的定义我们看到G取X的前两个参数,所以如果我们知道G我们有我们需要的所有东西来推断X的参数。我可以做一些不同的事情来帮助Scala进行推理吗?我有一个比X更多参数的类,现在我总是要明确定义它们。我试图看看是否有什么可以帮助Scala成功推断出类型。
答案 0 :(得分:3)
我猜你可以使用更高级的kinded类型:
case class X[Ao <: A, Bo <: B, Go[GAo <: Ao, GBo <: Bo] <: G[GAo, GBo]](a: Ao, b: List[Bo], g: Go[Ao, Bo])
class OO extends X(a,List(),g)
或者,如果您的类型参数是协变的:
case class G[+Ao <: A, +Bo <: B](a: Ao, b: Bo)
case class X[Ao <: A, Bo <: B, Go[_ <: Ao, _ <: Bo] <: G[Ao, Bo]](a: Ao, b: List[Bo], g: Go[Ao, Bo])
我从经验中知道,当scala编译器在相同组中的参数相互依赖时,它们不能推断出类型。&#34;不同的级别&#34;就像在这个例子中。较高的kinded类型允许我显式声明类型边界并帮助编译器推断出正确的类型。