2017-08-01 70 views
3

我正在寻找一种方法将两个HList拉链在一起。第一个是通过一般案例转换的案例类生成的,第二个是手动定义为Nat的HList。因此,我期望一个元组(或2个成员的HList)具有case类中的一个字段,并且Nat相关联。带静态Nat的HList邮编普通HList

目标是创建一个“可定制的”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] 

结果将要匹配的encoderTuple[H, N <: Nat, T <: HList]: Encoder[(H, N) :: T]或和encoderHList[H, N <: Nat, T <: HList]: Encoder[(H::N::HNil) :: T]

+0

亲爱@JulienLafont,它已经有一段时间,因为你问你的问题的,如果你有一个时刻,你可以检查如果我的[answer](https://stackoverflow.com/a/45914883/5249621)可以吗?谢谢。 –

回答

1

目标是创建一个“可定制的”ZipWithIndex

我猜标准shapeless.ops.hlist.Zip应该足够为:

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)