简体   繁体   English

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

[英]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]证据, BA的子类型,所以我希望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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM