trait Zipper[A <: HList, B] {
type Out <: HList
def zip(a: A, bs: Stream[B]): Out
}
implicit def hnilZipper[B] = new Zipper[HNil, B] {
type Out = HNil
def zip(a: HNil, bs: Stream[B]): HNil = HNil
}
implicit def consZipper[Head, Tail <: HList, B](implicit z: Zipper[Tail, B]) = new Zipper[Head :: Tail, B] {
type Out = (Head, B) :: z.Out
def zip(a: Head :: Tail, bs: Stream[B]): Out = {
(a.head, bs.head) :: z.zip(a.tail, bs.tail)
}
}
def zip[A <: HList, B](a: A, b: Stream[B])(implicit z: Zipper[A, B]): z.Out = z.zip(a, b)
Как отмечает Март, существуют проблемы с безопасностью, и это не удастся, если поток будет короче HList.Но вы можете довольно легко изменить это, чтобы вернуть Option[(A1, B) :: (A2, B) :: ...]
или (A1, Option[B]) :: (A2, Option[B]) :: ...
, если это проблема.