隐式搜索不指导类型推断在Scala中查找超类型

时间:2015-02-13 22:12:09

标签: scala type-inference implicits subtyping

我是以下代码,我有R[A]B的证据是A的子类型,因此我希望foo推断出{{1}的类型并使用A证据。但是,scalac拒绝这样做。

RA

我试过了:

trait R[T]

case class A(i: Int)

object A {

  implicit object RA extends R[A]

}

class B(i: Int) extends A(i)

def foo[T](x : T)(implicit ev: R[T]) = 0

println(foo(new B(1))) // infers T as B and fails to find implicit R[B]

println(foo(new B(1) : A)) // Works, but undesirable

但它仍然不起作用。

现在,如果我定义:

def foo[T, TT >: T](x : T)(implicit ev: R[TT]) = 0

推理有效,但在我的实际代码中,我需要参考TT。

编辑:现在我已经将A&C的证据转移到了A伴侣对象,这个解决方案似乎不再适用了。在现实环境中,证据将始终存在于伴随对象中,隐式搜索必须找到它。

另一个解决方案是让我的证据反变,但这会给我带来很多麻烦,例如推断def foo[T](x : T)(implicit ev: R[TT] forSome {type TT <: T}) = 0 和其他问题(我的实际代码比这个简化的例子更复杂)。

如何才能正常运作?

1 个答案:

答案 0 :(得分:0)

您可以使用

def foo[T, TT](x : T)(implicit ev: R[_ >: T] with R[TT]) = 0

并参考TT。

编辑:以下代码使用逆变来查找随播对象中的证据。它还编码TT是T的超类型。它不推断Nothing,但你已经提到了逆变的其他问题。有可能解决这些问题吗?

trait R[-T]

case class A(i: Int)

object A {

  implicit object RA extends R[A]

}

class B(i: Int) extends A(i)

def foo[T, TT](x : T)(implicit ev1: R[T] with R[TT], ev2: T <:< TT) = 0

println(foo(new B(1))) // infers TT as A