繁体   English   中英

如何在scala宏中获取更高kinded类型参数的树

[英]How to obtain a tree for a higher-kinded type parameter in a scala macro

我正在尝试编写一个宏来简化一些与monad相关的代码(我正在为Monads使用cat 1.6.0)。 现在我只想写出lift[F](a)其中F是一元型构造函数,并将其扩展为a.pure[F] 看起来很简单,但我不能让它工作。

现在我有这个代码来帮助进行类型推断:

object Macros {
  class LiftPartiallyApplied[F[_]] {
    def apply[A](a: A): F[A] = macro MacroImpl.liftImpl[F, A]
  }

  def lift[F[_]] = new LiftPartiallyApplied[F]
}

而对于宏的实际实现:

object MacroImpl {
  def liftImpl[F[_], A](c: blackbox.Context)(a: c.Tree)(implicit tt: c.WeakTypeTag[F[_]]): c.Tree = {
    import c.universe._
    q"$a.pure[${tt.tpe.typeConstructor}]"
  }
}

现在我可以像这个lift[List](42)一样调用宏lift[List](42)并且它会扩展到42.pure[List] ,很棒。 但是当我用更复杂的类型调用它时,例如lift[({type F[A] = Either[String, A]})#F](42) ,它将扩展为42.pure[Either] ,显然是坏了,因为Either是二进制类型的构造函数而不是一元的构造函数。 问题是我只是不知道放在那里而不是${tt.tpe.typeConstructor} ...

//编辑:由于人们显然无法重现问题,我已经建立了一个完整的存储库: https//github.com/mberndt123/macro-experiment我现在将尝试找出Dmytro和我自己项目之间的区别是。

不要将MainMacros放在同一个编译单元中。


但是当我用更复杂的类型调用它时,例如lift[({type F[A] = Either[String, A]})#F](42) ,它将扩展为42.pure[Either]

无法重现。

对我来说, lift[List](42)产生(使用scalacOptions += "-Ymacro-debug-lite"

Warning:scalac: 42.pure[List]
TypeApply(Select(Literal(Constant(42)), TermName("pure")), List(TypeTree()))

在编译时和运行时的List(42)

lift[({ type F[A] = Either[String, A] })#F](42)产生

Warning:scalac: 42.pure[[A]scala.util.Either[String,A]]
TypeApply(Select(Literal(Constant(42)), TermName("pure")), List(TypeTree()))

在编译时和在运行时Right(42)

这是我的项目https://gist.github.com/DmytroMitin/334c230a4f2f1fd3fe9e7e5a3bb10df5


你为什么需要宏? 你为什么不写

import cats.Applicative 
import cats.syntax.applicative._ 

class LiftPartiallyApplied[F[_]: Applicative] { 
  def apply[A](a: A): F[A] = a.pure[F] 
} 

def lift[F[_]: Applicative] = new LiftPartiallyApplied[F] 

好吧,我发现了问题所在。

宏需要与其使用站点分开编译。 我认为这意味着Macros需要与MacroImpl分开编译,所以我将它们放在单独的sbt子项目中,并在项目中调用Macros来定义Macros 但它实际上意味着宏的调用需要与其定义分开编译。 所以我将MacroImplMacros放在一个子项目中,并在另一个子项目中调用宏,它运行得很好。

感谢Dmytro花时间演示如何正确行事!

//编辑:看起来像Dmytro用他的评论打败了我:-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM