tri*_*oid 5 scala scala-macros scala-2.13
我正在编写宏将类型描述转换为单例类型:
object Type2String {
def apply[I]: Witness.Lt[String] = macro Macros.apply[I]
final class Macros(val c: whitebox.Context) extends MWithReflection {
import c.universe._
def apply[A: WeakTypeTag]: Tree = {
val tt: Type = weakTypeOf[A]
val str = tt.toString
// val vv = viz(tt)
q"shapeless.Witness.mkWitness[$str]($str)"
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是因为 A 只有一个 WeakTypeTag。它无法从泛型类型中提取正确的信息:
case class ^^[T1, T2]() {
final val wTSelf = Type2String[^^[T1, T2]]
}
val e1 = ^^[Int, String]()
e1.wTSelf
Run Code Online (Sandbox Code Playgroud)
这给出了错误的见证人类型: shapeless.Witness.Aux[String("T1 ^^ T2")]
所以我的问题是:
现在是编译时,类型信息应该是完全可见的,为什么T1和T2被擦除了?
如何修复此程序以提供正确的类型信息:
shapeless.Witness.Aux[String("Int ^^ String")]
?
对于第一个问题,@oleg-pyzhcov非常清楚地指出了问题:当你定义类时,你的宏被扩展,而这里编译器无法知道实际使用的是什么类型。
对于第二个问题,@oleg-pyzhcov 又是对的。事实上,有一个类似的例子,它使用隐式来解决您的问题(scala 2.10.2 用泛型类型调用“宏方法”不起作用)。
因此,我尝试稍微更改您的代码,以便成功返回正确的类型:
import scala.reflect.macros.whitebox
import scala.language.experimental.macros
trait Type2String[T] {
def apply() : Witness.Lt[String]
}
object Type2String {
implicit def materializeType2String[T]: Type2String[T] = macro impl[T]
def impl[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[Type2String[T]] = {
import c.universe._
val tt: Type = weakTypeOf[T]
val str = tt.toString
//val vv = viz(tt) I don't know what is viz(tt)...
reify {
() => c.Expr[Witness.Lt[String]](q"shapeless.Witness.mkWitness[$str]($str)").splice
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你必须在类定义中多写一些代码:
case class ^^[T1, T2]()(implicit val type2String: Type2String[^^[T1, T2]]) {
final val wTSelf = type2String()
}
//or
case class ^^^[T1, T2]() {
final def wTSelf(implicit type2String: Type2String[^^[T1, T2]]) = type2String()
}
val e1 = ^^[Int, String]()
//val e2 = ^^^[String, Double]()
e1.wTSelf
Run Code Online (Sandbox Code Playgroud)
那就是。
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |