Предположим, у меня есть класс case:
case class Foo(num: Int, str: String, bool: Boolean)
Теперь у меня также есть простая оболочка:
sealed trait Wrapper[T]
case class Wrapped[T](value: T) extends Wrapper[T]
(и некоторые другие реализации Wrapper, которые здесь не важны)
Я могу использовать Generic[Foo] для получения Aux, представляющего этот класс case: val genFoo = Generic[Foo]
(в моем реальном коде я использую LabelledGeneric, чтобы не потерять имена полей)
Это дает мне тип, представляющий определение списка HList:
Generic.Aux[Foo, Int :: String :: Boolean :: HNil]
(при использовании с LabelledGeneric определение намного сложнее, но по сути то же самое)
Теперь я хочу создать определение типа для HList, которое вместо необработанных типов включает в себя обернутые типы. Пример:
type WrappedHlist = Wrapper[Int] :: Wrapper[String] :: Wrapper[Boolean] :: HNil
Затем я могу использовать это определение типа, например, для создания кодировщика/декодера Circe (я предоставил необходимый кодировщик/декодер для типа Wrapper).
Вся необходимая информация существует во время компиляции, так как определение второго HList легко определяется из первого. Прямо сейчас я могу добиться этого, написав определение вручную или повторив определение case-класса Foo с избыточной версией, где все определено как Wrappers. Как я могу создать определение, которое не требует от меня повторения всего?