【问题标题】:Compile error when I mix Implicits, type parameters and Nothing当我混合隐式、类型参数和无时编译错误
【发布时间】:2014-05-21 09:13:01
【问题描述】:

为什么这不能用类型参数编译:

错误:value explode 不是 Test.A[Nothing] 的成员

如果我删除它们,那么它会编译。我不明白什么,更重要的是,我能做些什么来解决它。

object Test extends App {

  implicit class B[E](set: A[E]) {
    def explode() = println("boom")
  }

  case class A[E](name: String)

  A[Nothing]("coldplay").explode()
}

(本例中的类型参数不做任何事情,但在现实世界的用例中,我有多个类型参数,有些可以是 Nothing,有些不是)。

【问题讨论】:

  • 显然,直接将类型参数设置为Nothing 是导致问题的原因:裸A("coldplay").explode()(实际上是A[Nothing])和任何其他指定类型,例如,A[String]("coldplay").explode() 工作得很好。至于“为什么”,我会等待其他人回答,只是因为我不知道...... :)
  • 是的,我在现实世界的用例中没有使用任何东西,这就是它开始爆炸的时候。
  • 如果您使用-Xlog-implicit-conversions-Xlog-implicits,您可以获得更多信息。看起来 A("coldplay").explode() 有效,因为在解析类型参数之前应用了隐式转换。对于A[Nothing]("coldplay").explode(),编译器拒绝将Nothing 推断为B 的类型参数,尽管我不知道为什么。

标签: scala implicit


【解决方案1】:

它真的不喜欢推理:

scala> implicit def a2b(a: A[Nothing]): B[Nothing] = new B(a)
<console>:17: error: type mismatch;
 found   : A[Nothing]
 required: A[T]
Note: Nothing <: T, but class A is invariant in type E.
You may wish to define E as +E instead. (SLS 4.5)
       implicit def a2b(a: A[Nothing]): B[Nothing] = new B(a)
                                                           ^

scala> implicit def a2b(a: A[Nothing]): B[Nothing] = new B[Nothing](a)
warning: there were 1 feature warning(s); re-run with -feature for details
a2b: (a: A[Nothing])B[Nothing]

scala> A[Nothing]("coldplay").explode()
boom

-Ytyper-debug:

|    |    |    |    |    |    |    solving for (T: ?T)
|    |    |    |    |    |    |    |-- $iw.this.X.B BYVALmode-EXPRmode-FUNmode-POLYmode (silent solving: type T: method f in X) implicits disabled
|    |    |    |    |    |    |    |    [adapt] [T](set: $line3.$read.$iw.$iw.X.A[T])$line3.$read.$iw.$iw... adapted to [T](set: $line3.$read.$iw.$iw.X.A[T])$line3.$read.$iw.$iw...
|    |    |    |    |    |    |    |    \-> (set: X.A[T])X.B[T]
|    |    |    |    |    |    |    solving for (T: ?T, T: ?T)
|    |    |    |    |    |    |    \-> <error>
<console>:10: error: value explode is not a member of X.A[Nothing]
       def f() = A[Nothing]("coldplay").explode() }

【讨论】:

  • 为我工作。只是不要摆脱参数化的隐式转换——两者都在范围内。试试看。此外,此答案中的第一次尝试显示了另一种解决方案:class A[+E](...)
  • 我的课程在实际代码中已经是协变的,似乎没有帮助。
  • @monkjack 这在隐式类之外。
  • 是的,协方差并不重要,因为我的班级一直都是协变的。
  • A 或 B 协变。
猜你喜欢
  • 2014-08-12
  • 2014-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 2019-02-03
  • 2020-11-09
相关资源
最近更新 更多