在 Scala 中没有typeof
这种情况。
我们可以尝试修改添加类型参数的方法
def f[F](foo: F)(x: F)(implicit M: Monoid[F]) =
M.append(foo, M.append(x, foo))
并称其为,要替换的表达式在f(Foo)(...)
哪里,则应在编译时推断。Foo
F
否则我可以想象以下工作流程。我们可以使用 Scalameta 的SemanticDBFoo
从自身的字符串表示中生成表达式类型的字符串表示,然后插入表达式的字符串表示,然后生成该类型的字符串表示。Foo
Foo
另一种选择是生成带有宏注释的树
import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
class generate(foo: String) extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro generateMacro.impl
}
object generateMacro {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
val str: String = c.prefix.tree match {
case q"new generate($s)" => c.eval[String](c.Expr(s))
}
val tree = c.typecheck(c.parse(str))
val tpe = tree.tpe.widen
annottees match {
case q"$mods def $name[..$_](...$_): $_ = $_" :: _ =>
q"""
$mods def $name(x: $tpe)(implicit M: Monoid[$tpe]): $tpe =
M.append($tree, M.append(x, $tree))
"""
}
}
}
@generate("1 + 1")
def f(): Unit = ()
// def f(x: Int)(implicit M: Monoid[Int]): Int = M.append(2, M.append(x, 2))
https://github.com/travisbrown/type-provider-examples/
https://docs.scala-lang.org/overviews/macros/typeproviders.html
实际上,我想这与所要求的很接近
class TypeOf[A](a: A) {
type T = A
}
val tp = new TypeOf(Foo)
def f(x: tp.T)(implicit M: Monoid[tp.T]) = M.append(Foo, M.append(x, Foo))