У меня есть куча классов дел, которые имеют идентичные по форме аналоги в других запечатанных чертах (каждая запечатанная черта используется для исчерпывающего сопоставления с образцом в типизированных поведениях Akka), и я хочу преобразовать одну версию в другую с наименьшим количеством шаблонов.
Черты выглядят примерно так:
object RoutingCommands {
sealed trait Command
final case class ProtocolMsg(name: String, id: Int) extends Command
}
object ProtocolCommands {
sealed trait Command
final case class ProtocolMsg(name: String, id: Int) extends Command
}
Я знаю, что могу сделать преобразование, используя shapeless.Generic
, например:
val msg1 = ProtocolCommands.ProtocolMsg("foo", 1)
val msg2 = Generic[RoutingCommands.ProtocolMsg].from(
Generic[ProtocolCommands.ProtocolMsg].to(msg1)
)
Но необходимость делать это для каждого преобразования - это больше, чем просто
построение падежных классов вручную. В идеале мне нужен конвертер, который выводит приведенный выше код на основе двух типов, предоставляемых во время компиляции, таких как val msg2 = convert(msg1)
В качестве шага к этому я попытался разбить его на что-то вроде:
def convert[A,B](a: A): B = Generic[B].from(
Generic[A].to(a)
)
но это приводит к:
Error:(55, 44) could not find implicit value for parameter gen: shapeless.Generic[B]
При копании кажется, что мне нужно использовать Generic.Aux
, что приводит меня к:
def convert[A, B, HL <: HList](a: A)(
implicit
genA: Generic.Aux[A, HL],
genB: Generic.Aux[B, HL]
) = genB.from(genA.to(a))
Который, когда вызывается с:
val msg3 = convert(msg2)
Результат:
Error:(61, 57) could not find implicit value for parameter genB: shapeless.Generic.Aux[B,HL]
Это понятно, поскольку нигде не определен тип возвращаемого значения. Однако я выясняю, как дать подсказку, что такое B
, чтобы genB
можно было получить неявно.