在 Scala 2 或 3 中,是否可以在运行时调试隐式解析过程? [英] In scala 2 or 3, is it possible to debug implicit resolution process in runtime?

查看:16
本文介绍了在 Scala 2 或 3 中,是否可以在运行时调试隐式解析过程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 scala 语言中,隐式解析通常在编译时完成,有时会抛出混淆的错误信息,此类错误的一个著名例子是 shapeless Generic 抛出错误信息,如:

In scala language, implicit resolution is often done in compile-time and sometimes throws obfuscating error information, one famous example of such error is when shapeless Generic throws error information like:

error: could not find implicit value for parameter encoder: CsvEncoder[Foo]

(参见 https://books.underscore.io/shapeless-guide/shapeless-guide.html 详情)

这个问题的解决方案是在运行时运行隐式解析算法(内部应该是图查询算法),这至少有两个好处:

A solution to this problem is to run implicit resolution algorithm (should be a graph query algorithm internally) in runtime, this has at least 2 benefits:

  • 可以使用调试工具一步步重现解析过程,所以即使是错误信息&文档不完整,很容易发现错误.

  • debugging tools can be used to reproduce the resolution process step-by-step, so even error information & documentations are incomplete it would be easy to spot the error.

在许多情况下,类型信息在编译时是不可能确定的(例如,类型取决于控制流).如果隐式转换不能延迟到运行时阶段,那么定义隐式转换的许多好处将无效.

in many cases type information can be impossible to be determined in compile-time (e.g. type depending on the control flow). If implicit conversion cannot be delayed to runtime phase, many benefit of defining implicit conversion will be nullified.

所以我的问题是,Scala 2.x 或 Dotty 中是否存在此功能?还是在路线图上?

So my question is, does this feature exist in Scala 2.x or Dotty? Or is it on the roadmap?

非常感谢您的意见.

推荐答案

您可以在编译时调试隐式:

You can debug implicits at compile time:

  1. 开启-Xlog-implicits

尝试手动解析隐式(也可能指定类型参数)并查看编译错误

try to resolve implicits manually (maybe specifying type parameters as well) and see compile errors

implicitly[...](...manually...)

  • 使用 scala.reflect

    println(reify { implicitly[...] }.tree)
    

  • 使用 IDE 功能来显示隐式

  • use IDE functionality to show implicits

    使用带有编译器内部的宏可以调试隐式解析

    using macros with compiler internals you can debug implicit resolution

    是否有一个类型类可以检查是否存在至少一个隐式类型?

    创建一个模糊的低优先级隐式

    使用Prolog斯卡拉"找到可用的类型类实例

    寻找第二个隐式匹配

    https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/package.scala#L119-L168

    如果您正在开发类型类,请不要忘记使用注释 @implicitNotFound@implicitAmbiguous.

    If you're developing a type class don't forget to use annotations @implicitNotFound and @implicitAmbiguous.

    您始终可以将程序的编译推迟到运行时.所以代替程序

    You can always postpone compilation of your program till runtime. So instead of program

    object App {
      def main(args: Array[String]): Unit = {
        println("test") // test
      }
    }
    

    你可以拥有

    import scala.reflect.runtime.currentMirror
    import scala.reflect.runtime.universe._
    import scala.tools.reflect.ToolBox
    val toolbox = currentMirror.mkToolBox()
    
    toolbox.eval(q"""
      object App {
        def main(args: Array[String]): Unit = {
          println("test")
        }
      }
    
      App.main(Array())
    """) // test
    

    而不是

    implicitly[Numeric[Int]]
    

    你可以拥有

    toolbox.compile(q"""
      implicitly[Numeric[Int]]
    """)
    

    toolbox.inferImplicitValue(
      toolbox.typecheck(tq"Numeric[Int]", mode = toolbox.TYPEmode).tpe, 
      silent = false
    )
    

    但是认为将程序编译推迟到运行时您将能够在运行时而不是在编译时更容易地调试隐式的想法过于乐观了.实际上将程序编译推迟到运行时你会增加一层间接,即使事情更难调试.

    But it's too optimistic to think that postponing program compilation till runtime you'll be able to debug implicits easier at runtime rather than at compile time. Actually postponing program compilation till runtime you add one level of indirection more i.e. make things harder to debug.

    这篇关于在 Scala 2 或 3 中,是否可以在运行时调试隐式解析过程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆