Zip Generic HList with static Nat HList
I am looking for a way to pin two HLists together. The first one is generated from the case class converted to its generic representation, and the second one is manually defined as an HList from Nat.
As a result, I expect a tuple (or 2-member HList) with one field from the case class, and the associated Nat.
The goal is to create "custom" ZipWithIndex
.
def derive[A, I <: HList, R <: HList, Z <: HList](implicit
gen: Generic.Aux[A, R],
zipper: Zip.Aux[R, I, Z],
enc: Lazy[Encoder[Z]])(a: A): Deriver[A] = {
val genRepr = gen.to(A)
val zipped = zip(genRepr :: ??? :: HNil)
enc.value(zipped)
}
case class Foo(a: String, b: String, c: String)
derive[Foo, Nat._1 :: Nat._3 :: Nat.7 :: HNil]
The result must match encoderTuple[H, N <: Nat, T <: HList]: Encoder[(H, N) :: T]
either or encoderHList[H, N <: Nat, T <: HList]: Encoder[(H::N::HNil) :: T]
.
source to share
The goal is to create "custom"
ZipWithIndex
.
I guess the standard shapeless.ops.hlist.Zip is enough for this:
trait Encoder[Z] {
type Out
def apply(z: Z): Out
}
object Encoder {
type Aux[Z, Out0] = Encoder[Z] { type Out = Out0 }
// implicits
}
trait Deriver[A]
object Deriver {
// implicits
}
def derive[A, I <: HList, R <: HList, Z <: HList](a: A, i: I)(implicit
gen: Generic.Aux[A, R],
zipper: Zip.Aux[R :: I :: HNil, Z],
enc: Lazy[Encoder.Aux[Z, Deriver[A]]]): Deriver[A] = {
val genRepr: R = gen.to(a)
val zipped: Z = zipper(genRepr :: i :: HNil)
enc.value(zipped)
}
case class Foo(a: String, b: String, c: String)
// derive[Foo, Nat._1 :: Nat._3 :: Nat._7 :: HNil, ???, ???]
derive(Foo("aaa", "bbb", "ccc"), Nat._1 :: Nat._3 :: Nat._7 :: HNil)
source to share