Смешивание магнолии с трюком Цирцеи для автоматического получения
У меня есть класс типов и я хочу предоставить пользователям полуавтоматический и автоматический вывод. У меня есть рабочая реализация, основанная на Magnolia, и она работает очень хорошо. Есть черта, дающая определения Typeclass[A]
, combine[A]
а также dispatch[A]
, тогда оба типа деривации доступны с
final object semiauto extends Derivation {
def deriveFormat[A]: Typeclass[A] = macro Magnolia.gen[A]
}
final object auto extends Derivation {
implicit def deriveFormat[A]: Typeclass[A] = macro Magnolia.gen[A]
}
Ничего удивительного. Не удивительно, что когда пользователи приносят auto._
в область видимости затмевает эффективные деривации, написанные для определенных типов.
Я надеялся, что смогу использовать ту же технику, которую разработал Трэвис Браун для Circe, которая в основном работает так:
Определите класс значения заполнителя, который может содержать любое значение
case class Exported[A](instance: A) extends AnyVal
Предоставить низкоприоритетный автоматический вывод для моего класса типов, когда значение этого класса находится в области видимости
object DynamoFormat extends LowPriorityDerivation {
// derivation for specific types
...
}
trait LowPriorityDerivation {
implicit def deriveExported[A](implicit e: Exported[DynamoFormat[A]]) =
e.instance
}
Наконец, скрыть автоматический вывод экспортируемых объектов вauto
final object auto extends Derivation {
implicit def derive[A]: Exported[DynamoFormat[A]] =
Exported(semiauto.deriveFormat[A])
}
К сожалению, есть ошибка компиляции при попытке вызвать макрос:
magnolia: could not infer auto.Typeclass for type com.gu.scanamo.DynamoFormat[A]
Exported(deriveDynamoFormat[A])
^
Я слишком долго смотрю на этот код, потому что не могу найти выход; любая помощь будет принята с благодарностью.
1 ответ
Может быть, вы можете использовать макрос обернуть его
object MacroWrap {
def typeName[T]: String = macro typeNameImpl[T]
def typeNameImpl[T: c.WeakTypeTag](c: blackbox.Context): c.universe.Tree = {
import c.universe._
q"${c.weakTypeOf[T].toString}"
}
def typeNameWeak[T]: String = macro typeNameWeakImpl[T]
def typeNameWeakImpl[T: c.WeakTypeTag](c: blackbox.Context) = {
import c.universe._
q"${reify(MacroWrap)}.typeName[${weakTypeOf[T]}]"
}
}
//тестовое задание
println(MacroWrap.typeNameWeak[String]) // will print String