Using the “Prolog in Scala” to find available type class instances

后端 未结 1 1953
时光取名叫无心
时光取名叫无心 2021-02-03 18:27

Considering https://speakerdeck.com/folone/theres-a-prolog-in-your-scala, I would like to \"abuse\" the Scala type system to find all instances of e.g. CanBuildFrom

1条回答
  •  时光说笑
    2021-02-03 18:54

    This can be done (at least in some cases) with compiler internals

    import scala.language.experimental.macros
    import scala.reflect.internal.util
    import scala.reflect.macros.{blackbox, contexts}
    
    object Macros {
    
      def allImplicits[A]: List[String] = macro impl[A]
    
      def impl[A: c.WeakTypeTag](c: blackbox.Context): c.Tree = {
        import c.universe._
    
        val context = c.asInstanceOf[contexts.Context]
        val global: context.universe.type = context.universe
        val analyzer: global.analyzer.type = global.analyzer
        val callsiteContext = context.callsiteTyper.context
    
        val tpA = weakTypeOf[A]
    
        val search = new analyzer.ImplicitSearch(
          tree = EmptyTree.asInstanceOf[global.Tree],
          pt = tpA.asInstanceOf[global.Type],
          isView = false,
          context0 = callsiteContext.makeImplicit(reportAmbiguousErrors = false),
          pos0 = c.enclosingPosition.asInstanceOf[util.Position]
        )
    
        q"${search.allImplicits.map(_.tree.symbol.toString).distinct}"
      }
    }
    
    allImplicits[CanFoo[_, String]]
    // List(value canFooBoolString, value canFooDblString, value canFooIntString)
    

    Tested in 2.13.0.

    0 讨论(0)
提交回复
热议问题