Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
224 views
in Technique[技术] by (71.8m points)

In scala 2 or 3, is it possible to debug implicit resolution process in runtime?

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]

(see https://books.underscore.io/shapeless-guide/shapeless-guide.html for detail)

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.

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

Thanks a lot for your opinion.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can debug implicits at compile time:

  1. switch on -Xlog-implicits

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

    implicitly[...](...manually...)
    
  3. use scala.reflect

    println(reify { implicitly[...] }.tree)
    
  4. use IDE functionality to show implicits

  5. using macros with compiler internals you can debug implicit resolution

    Is there a type-class that checks for existence of at least one implicit of a type?

    create an ambiguous low priority implicit

    Using the "Prolog in Scala" to find available type class instances

    Finding the second matching implicit

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

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
  }
}

you can have

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

And instead of

implicitly[Numeric[Int]]

you can have

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

or

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...