Scala-隐式宏&物化 [英] Scala - implicit macros & materialisation

查看:107
本文介绍了Scala-隐式宏&物化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

隐式宏的用例应该是类型类实例的所谓实现".

The use cases for implicit macros is supposed to be the so-called "materialisation" of type class instances.

不幸的是,文档中的示例有点模糊如何实现的.

Unfortunately, the example in the documentation is a bit vague on how that is achieved.

在被调用时,实现器可以获取T的表示形式并生成Showable类型类的适当实例.

Upon being invoked, the materializer can acquire a representation of T and generate the appropriate instance of the Showable type class.

假设我具有以下特征...

Let's say I have the following trait ...

trait PrettyPrinter[T]{
  def printed(x:T) : String
}
object PrettyPrinter{
  def pretty[T](x:T)(implicit pretty:PrettyPrinter[T]) = pretty printed x

  implicit def prettyList[T](implicit pretty :PrettyPrinter[T]) = new PrettyPrinter[List[T]] {
    def printed(x:List[T]) = x.map(pretty.printed).mkString("List(",", ",")")
  }
}

和三个测试班

class A(val x:Int)
class B(val x:Int)
class C(val x:Int)

现在我了解到,与其编写下面的样板

Now I understand that instead of writing the following boilerplate

implicit def aPrinter = new PrettyPrinter[A] {def printed(a:A) = s"A(${a.x})"}
implicit def bPrinter = new PrettyPrinter[B] {def printed(b:B) = s"B(${b.x})"}
implicit def cPrinter = new PrettyPrinter[C] {def printed(c:C) = s"C(${c.x})"}

我们应该能够添加

implicit def materialise[T] : PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T](c:blackbox.Context):c.Expr[PrettyPrinter[T]] = {
  import c.universe._

  ???
}

object PrettyPrinter{...},然后按需生成相应的PrettyPrinters……如何?我实际上如何获得"T的表示形式"?

to the object PrettyPrinter{...} which then generates the corresponding PrettyPrinters on demand ... how? How do I actually get that "representation of T"?

如果我尝试c.typeOf[T],例如,"T没有可用的TypeTag".

If I try c.typeOf[T], for example, "No TypeTag available for T".

更新

尝试使用类标签似乎也不起作用.

Trying to use class tags doesn't seem to work either.

implicit def materialise[T:ClassTag] : PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T:ClassTag](c:blackbox.Context):c.Expr[PrettyPrinter[T]] = {
  import c.universe._

  ???
}

产生

Error:(17, 69) macro implementations cannot have implicit parameters other than WeakTypeTag evidences
implicit def materialise[T:ClassTag] : PrettyPrinter[T] = macro implMaterialise[T]
                                                                ^

update2

有趣的是,使用WeakTypeTags并不会真正改变

Interestingly, using WeakTypeTags doesn't really change anything as

implicit def materialise[T:WeakTypeTag]: PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T](c:blackbox.Context)(implicit evidence : WeakTypeTag[T]):c.Expr[PrettyPrinter[T]]
= {
  import c.universe._

  ???
}

将导致

Error:(18, 71) macro implementations cannot have implicit parameters other than WeakTypeTag evidences
implicit def materialise[T:WeakTypeTag]: PrettyPrinter[T] = macro implMaterialise[T]
                                           ^

推荐答案

我实际上如何获得"T的表示形式"?

How do I actually get that "representation of T"?

您需要使用c.WeakTypeTag,如在更新"部分中找到的编译器消息所提示.

You need to use c.WeakTypeTag, as hinted at by the compiler message you found in your "UPDATE" section.

该项目有一个可以修改的工作示例:

This project has a working example that you can adapt: https://github.com/underscoreio/essential-macros/blob/master/printtype/lib/src/main/scala/PrintType.scala

object PrintTypeApp extends App {
  import PrintType._

  printSymbol[List[Int]]
}

import scala.language.experimental.macros

import scala.reflect.macros.blackbox.Context
import scala.util.{ Try => ScalaTry }

object PrintType {
  // Macro that generates a `println` statement to print
  // declaration information of type `A`.
  //
  // This only prints meaningful output if we can inspect
  // `A` to get at its definition:
  def printSymbol[A]: Unit =
    macro PrintTypeMacros.printTypeSymbolMacro[A]
}

class PrintTypeMacros(val c: Context) {
  import c.universe._

  def printTypeSymbolMacro[A: c.WeakTypeTag]: c.Tree =
    printSymbol(weakTypeOf[A].typeSymbol, "")
}

这篇关于Scala-隐式宏&物化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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