给定一个类型构造函数/容器F[_]
,我想创建一个组合器,它可以通过以下规则集将多态类型和 hlist 类型组合到一个新容器中:
F[HNil]
并F[HNil]
进入一个F[HNil]
F[A]
并F[HNil]
进入一个F[A :: HNil]
F[HNil]
并F[A]
进入一个F[A :: HNil]
F[A]
并F[B]
进入一个F[A :: B :: HNil]
F[L <: HList]
并F[R <: HList]
进入F[L :: R]
(hlist concat)F[A]
并F[R <: HList]
进入F[A :: R]
(hlist prepend)F[L <: HList]
并F[B]
进入F[L :: B :: HNil]
(hlist append)
有没有一种很好的方法可以在无形中做到这一点?或者有没有更简单的方法来解决这个特殊问题:) 问题是我有组合器,它们产生一个F[Int]
,F[HNil]
和F[HNil]
. 例如,将这些结合起来不应产生F[Int :: HNil :: HNil]
(but F[Int :: HNil]
)。为此,我现在制作了 typeclass:
trait CodecAppender[F, A, B] {
type Out
final type CodecOut = Codec[F, Out]
def apply(a: Codec[F, A], b: Codec[F, B]): CodecOut
}
object CodecAppender {
type Aux[F, A, B, C] = CodecAppender[F, A, B] { type Out = C }
private def make[F, A, B, C](decompose: C => (A, B))(implicit S: Monoid[F], D: DecoderAppender.Aux[F, A, B, C]): Aux[F, A, B, C] = new CodecAppender[F, A, B] {
type Out = C
def apply(a: Codec[F, A], b: Codec[F, B]): CodecOut = new Codec[F, C] {
def encode(in: C) = {
val (head, tail) = decompose(in)
a.encode(head) |+| b.encode(tail)
}
val decoder = D.append(a.decoder, b.decoder)
}
}
implicit def HNilAndHNil[F, O](implicit M: Monoid[F],
D: DecoderAppender.Aux[F, HNil, HNil, HNil]) =
make[F, HNil, HNil, HNil](r => HNil -> HNil)
//other cases omitted, but there are 6 more (which I described above)
}