scala - "illegal cyclic reference"涉及隐式的解释

标签 scala implicit cyclic-reference

在我的项目中,我有一个类型 A ,用于一些地方的参数,我希望一堆类型自动转换为该类型。我已经使用 A 的伴随对象中的一些隐式类实现了这一点。 .我已经删除了触发问题所不需要的所有内容:

trait A
object A {
  implicit class SeqA[T](v: Seq[T])(implicit x: T => A) extends A
  implicit class IntA(v: Int) extends A
  implicit class TupleA(v: (Int, Int)) extends SeqA(Seq(v._1, v._2))
}

但是scalac由于非法循环引用而拒绝此代码:
$ scalac -version
Scala compiler version 2.12.8 -- Copyright 2002-2018, LAMP/EPFL and Lightbend, Inc.
$ scalac A.scala 
A.scala:5: error: illegal cyclic reference involving class TupleA
  implicit class TupleA(v: (Int, Int)) extends SeqA(Seq(v._1, v._2))
                 ^
one error found

这里究竟有什么问题?编译器要执行/推断/解析涉及非法循环的内容是什么?

实现这些隐式类的有效方法的加分项。

最佳答案

您遇到了 SI-9553 ,一个三年半前的编译器错误。

该错误尚未修复的部分原因可能是有一个非常简单的解决方法——只需在您要扩展的泛型类上放置一个显式类型参数:

trait A
object A {
  implicit class SeqA[T](v: Seq[T])(implicit x: T => A) extends A
  implicit class IntA(v: Int) extends A
  implicit class TupleA(v: (Int, Int)) extends SeqA[Int](Seq(v._1, v._2))
}

无论如何,这可能是一个好主意,因为每当您让类型参数在涉及隐式定义的地方被推断出来时,您都会自找麻烦。

作为旁注,您可以使用像 -Xprint:typer 这样的编译器选项来调查这样的问题。 .在这种情况下,它在 REPL 中显示以下内容:
// ...
implicit class TupleA extends $line6.$read.$iw.$iw.A.SeqA[Int] {
  <paramaccessor> private[this] val v: (Int, Int) = _;
  def <init>(v: (Int, Int)): $line6.$read.$iw.$iw.A.TupleA = {
    TupleA.super.<init>(scala.collection.Seq.apply[Int](v._1, v._2))({
      ((v: Int) => A.this.IntA(v))
    });
    ()
  }
};
implicit <synthetic> def <TupleA: error>(v: (Int, Int)): <error> = new TupleA(v)

在这种情况下,这不是很有帮助,但它至少表明问题发生在 TupleA 的合成转换方法的定义中。隐式类,而不是在此之前的某个时间点。

关于scala - "illegal cyclic reference"涉及隐式的解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54804298/

相关文章:

Scala:包不能表示为 URI

scala - 类型类和带有单例类型/案例对象的隐式

scala - 在 Scala 中提供类型类的实例时使用 vals 还是 object 更好

token - 无法为非组合语法中的字符串文字创建隐式标记

循环引用特征的 Scala 类型错误

python - 如何正确处理 Python 中的循环模块依赖?

arrays - 如何访问数据框列中的数组元素(标量)

java - 将大 POJO 转换为案例类

scala - Akka:如何将消息内容包装到 HTTP 响应中?

c++ - 循环模板