我正在尝试实现(简化)特征的一个实例
trait TC[F[_]] {
def apply[A](fa: F[A]): F[A]
}
使用Scala宏。因此,宏的签名为
def materialize[F[_]](c: Context)(
implicit fT: c.WeakTypeTag[F[_]]): c.Expr[TC[F]]
F[_]
现在A
,出于以下两个原因,需要将类型构造函数应用于type参数:
apply
特定内容F
(如Foo[A]
)写以上签名Foo[A]
以指定一个有趣的主体apply
有没有什么方法来创建对应的方法类型参数的类型A
是能够比使用appliedType
?对我来说似乎很困难,因为方法apply
及其类型参数A
也只是作为树生成。
我试图WeakTypeTag[TC[F]]
作为宏调用的附加参数,并通过以下方式接收了参数类型
val paramT = wfg.tpe.member("apply": TermName).tpe.typeParams.head.tpe
但是使用paramT
inq"... def apply[$paramT] ..."
确实会导致
java.lang.IllegalArgumentException: can't splice "A" as type parameter
因此这似乎也无济于事。
我通过将上述特征的定义更改为
trait TC[F[_]] {
type ApplyF[A] = F[A]
def apply[A](fa: ApplyF[A]): ApplyF[A]
}
然后对树进行类型检查以获取虚拟值:
typecheck(q"""new TC[Foo] {
def apply[A](fa: ApplyF[A]): ApplyF[A] = ???
}""").tpe
然后可以销毁和检查类型检查的结果(通过树形转换器)以填充???
。这不能完全解决问题,产生类型错误:
found : A(in method apply)(in method apply)(in method apply)...
required: A(in method apply)(in method apply)(in method apply)...
虽然untypecheck
在返回树之前进行调用并没有帮助-但是对生成的树的检查显示,预期结果是有效的(类型正确)Scala代码。因此,使宏最终运行的最后一步是调用
parse(showCode(result))
感觉完全没有必要,但是这似乎是摆脱冲突类型信息的唯一方法。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句