我是以下代码,我有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
和其他问题(我的实际代码比这个简化的例子更复杂)。
如何才能正常运作?
答案 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