[英]Implicit search does not guide type inference to find a supertype in Scala
I the following code, I have evidence of R[A]
and B
is a subtype of A
, so I would expect foo
to infer the type of A
and use the RA
evidence. 我有以下代码,我有R[A]
证据, B
是A
的子类型,所以我希望foo
推断A
的类型并使用RA
证据。 However, scalac refuses to do so. 但是,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
I tried this: 我试过这个:
def foo[T, TT >: T](x : T)(implicit ev: R[TT]) = 0
But it still does not work. 但它仍然无效。
Now, if I define: 现在,如果我定义:
def foo[T](x : T)(implicit ev: R[TT] forSome {type TT <: T}) = 0
inference works, but in my actual code I need to refer to TT. 推理工作,但在我的实际代码中,我需要参考TT。
Edit: now that I've moved A's evidence to the A companion object, this solution seems to not work anymore. 编辑:现在我已经将A的证据移到了A伴侣对象,这个解决方案似乎不再适用了。 In a realistic setting, the evidence will always be in the companion object and implicit search has to find it. 在现实环境中,证据将始终存在于伴随对象中,隐式搜索必须找到它。
Another solution is to make my evidence contravariant but this causes a lot of trouble for me like inferring Nothing
and other problems (My actual code is more complex than this simplified example). 另一个解决方案是使我的证据逆变,但这对我来说很麻烦,比如推断Nothing
和其他问题(我的实际代码比这个简化的例子更复杂)。
How can I make this work correctly? 我怎样才能正常工作?
You could use 你可以用
def foo[T, TT](x : T)(implicit ev: R[_ >: T] with R[TT]) = 0
and refer to TT. 并参考TT。
Edit: The following code uses contravariance to find the evidence in the companion object. 编辑:以下代码使用逆变来查找伴随对象中的证据。 It also encodes that TT is a supertype of T. It doesn't infer Nothing
, but you've mentioned other problems with contravariance. 它还编码TT是T的超类型。它没有推断出Nothing
,但你已经提到了其他逆变问题。 Is it possible to work around those? 有可能解决这些问题吗?
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.