Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 在宏中计算shapless.Witness.Aux[T]类型的表达式失败_Scala_Macros_Scala Macros_Shapeless_Scala 2.11 - Fatal编程技术网

Scala 在宏中计算shapless.Witness.Aux[T]类型的表达式失败

Scala 在宏中计算shapless.Witness.Aux[T]类型的表达式失败,scala,macros,scala-macros,shapeless,scala-2.11,Scala,Macros,Scala Macros,Shapeless,Scala 2.11,我试图在宏中计算shapeless.Witness.Aux[T]类型的隐式参数,以便使用单例类型T的值。这是一个最小的示例: import shapeless.Witness import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context object Macro { def foo[N](implicit aux: Witness.Aux[N]): Unit = macro fo

我试图在宏中计算shapeless.Witness.Aux[T]类型的隐式参数,以便使用单例类型T的值。这是一个最小的示例:

import shapeless.Witness
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

object Macro {
  def foo[N](implicit aux: Witness.Aux[N]): Unit = macro fooImpl[N]

  def fooImpl[N: c.WeakTypeTag](c: Context)
                               (aux: c.Expr[Witness.Aux[N]]): c.Expr[Unit] = {
    import c.universe._

    val typechecked = aux.tree
    println("Typechecked tree:")
    println(show(typechecked))

    val untypechecked = c.untypecheck(typechecked)
    println("Untypechecked tree:")
    println(show(untypechecked))

    def eval = c.eval(c.Expr(untypechecked))
    val w = scala.util.Try(eval).getOrElse(eval)
    // now use w.value
    c.Expr[Unit](q"()")
  }
}
但是编辑这个

val w = shapeless.Witness(true)
Macro.foo[w.T]
失败,出现以下错误:

[error] overriding value value in trait Witness of type fresh$macro$2.this.T;
[error] value value has incompatible type
printlnshowtypechecked的输出为:

在我看来,问题在于,在非类型检查树中,value方法的类型为Boolean,而value字段的类型为Booleantrue,编译器需要这两种类型相同

有没有办法解决这个问题?是否支持在宏中计算宏


顺便说一句:这个项目包含的是一个复制这个的最小项目。

这个问题随着shapeless 2.2.2的改变而消失。

我猜你在这里试图做的是将编译时值偷偷带到宏实现中,以便可以在编译时计算中使用它吗?@MilesSabin听起来不错正当这是在库的上下文中出现的,我希望这个refinellit[matchesregx[shapeless.Witness.`[0-9]+`.T],String]123在编译时检查字符串123是否与regex[0-9]+.Gotcha.Witness匹配。它真正用于将单例类型映射到运行时值。我认为您最好直接使用类型参数N及其类型标记,然后在内部重用Witness的逻辑。一个相当简单的方法是将见证宏的大部分分解成一个可以由您自己的宏混合的特征。感谢@MilesSabin提供您的答案,尽管这不是我希望的答案。:-看来我需要深入到宏观领域。使问题稍微复杂一点的是,有一个与refineLit相当的运行时名为refine,它基于相同的验证机制,并且Witness可以完美地工作。如果您也需要一个运行时版本,那么这可能会改变情况。我怀疑您上面的问题是,取消类型检查后再重新类型检查是非常困难的保证是身份。你能以检查过的形式评估这棵树吗?另外,请记住,在编译时评估任意代码可能。。。危险的-
{
  final class fresh$macro$2 extends AnyRef with shapeless.Witness {
    def <init>(): fresh$macro$2 = {
      fresh$macro$2.super.<init>();
      ()
    };
    type T = Boolean(true);
    private[this] val value: Boolean(true) = true;
    <stable> <accessor> def value: Boolean(true) = true
  };
  new fresh$macro$2()
}
{
  final class fresh$macro$2 extends AnyRef with _root_.shapeless.Witness {
    def <init>() = {
      super.<init>();
      ()
    };
    type T = Boolean(true);
    private[this] val value: Boolean(true) = true;
    <stable> <accessor> def value: Boolean = true
  };
  new fresh$macro$2()
}