代码之家  ›  专栏  ›  技术社区  ›  Vasiliy Ivashin

具有隐式转换的typeclass中的堆栈溢出

  •  2
  • Vasiliy Ivashin  · 技术社区  · 7 年前

    我做了一个普通的 DynamoFormat Scanamo Circe Encoder Decoder 作为Json字符串定义到数据库中。

    import com.gu.scanamo.DynamoFormat
    import io.circe.parser.parse
    import io.circe.syntax._
    import io.circe.{Decoder, Encoder}
    
    object JsonDynamoFormat {    
      def forType[T: Encoder: Decoder]: DynamoFormat[T] = DynamoFormat.coercedXmap[T, String, Exception] {
        s => parse(s).flatMap(_.as[T]).fold(err => throw err, obj => obj)
      } {
        obj => obj.asJson.noSpaces
      }
    }
    

    object JsonDynamoFormat )自动提供这些格式化程序。

    implicit def jsonToFormat[T: Encoder: Decoder]: DynamoFormat[T] = JsonDynamoFormat.forType[T]
    

    当我导入它时,编译器成功地解析了格式化程序,但在运行时,我在 JsonDynamoFormat ,其中调用 jsonToFormat forType 无限交替:

    Exception in thread "main" java.lang.StackOverflowError
        at JsonDynamoFormat$.forType(JsonDynamoFormat.scala:12)
        at JsonDynamoFormat$.jsonToFormat(JsonDynamoFormat.scala:9)
        at JsonDynamoFormat$.forType(JsonDynamoFormat.scala:13)
        at JsonDynamoFormat$.jsonToFormat(JsonDynamoFormat.scala:9)
        ...
    

    1 回复  |  直到 7 年前
        1
  •  2
  •   Haspemulator    7 年前

    调试Scala隐式错误可能相当繁重。以下是一些有帮助的建议:

    • 使可能 scalacOptions ++= Seq("-Xlog-implicits") 编译器选项。这将打印隐式搜索日志,有助于了解隐式链在何处断裂。

    • libraryDependencies ++= Seq(compilerPlugin("io.tryp" %% "splain" % "0.2.4")) 提高隐式调试日志的可读性。

    通常,使用泛型派生的TypeClass在运行时发生堆栈溢出是错误的隐式解析的标志。这通常意味着编译器找到了几个循环相关隐式,并使用其中一个隐式来满足另一个隐式,反之亦然。

    Lazy typeclass从shapeless开始。然而,在实际的错误循环隐式的情况下,这将导致运行时错误,而不是编译时错误。