3

在下面的代码中,我有证据R[A]并且B是 的子类型A,所以我希望foo推断出证据的类型A并使用RA证据。然而,scalac 拒绝这样做。

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

但它仍然不起作用。

现在,如果我定义:

def foo[T](x : T)(implicit ev: R[TT] forSome {type TT <: T}) = 0

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

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

另一个解决方案是让我的证据逆变,但这会给我带来很多麻烦,比如推断Nothing和其他问题(我的实际代码比这个简化的例子更复杂)。

我怎样才能使它正常工作?

4

1 回答 1

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
于 2015-02-21T07:09:54.553 回答