Я пытаюсь написать макрос, чтобы упростить некоторый связанный с монадами код (я использую кошек 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)
, и он расширится до 42.pure[List]
, отлично.Но когда я вызываю его более сложным типом, таким как lift[({type F[A] = Either[String, A]})#F](42)
, он расширяется до 42.pure[Either]
, что явно не работает, поскольку Either
является конструктором двоичного типа, а не унарным.Проблема в том, что я просто не знаю, что там поставить вместо ${tt.tpe.typeConstructor}
…
// edit: поскольку у людей, видимо, возникают проблемы с воспроизведением проблемы, я сделал полный репозиторий: https://github.com/mberndt123/macro-experiment Сейчас я попытаюсь выяснить, в чем разница между Дмитрием и моим собственным проектом.