Scala-隐式宏&物化 [英] Scala - implicit macros & materialisation
问题描述
隐式宏的用例应该是类型类实例的所谓实现".
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屋!