Search code examples
scalashapeless

How to zip an HList with a plain Scala collection?


How to zip an HList with, let's say, a Scala Stream to produce an HList of pairs? Specifically:

import shapeless._

val a = 1.3 :: true :: "z" :: HNil
val b = Stream.from(1)

val ab: (Double, Int) :: (Boolean, Int) :: (String, Int) :: HNil = ???

Solution

  • It's possible, but there are restrictions. Mostly you have to specify the desired length of the Scala collection to be zipped. The result will, of course, be the length of the shorter of the two HLists.

    import shapeless._
    import syntax.std.traversable._  // toHList
    
    val a = 1.3 :: true :: "z" :: HNil  // 3 elements
    
    val short_b = Stream.from(1).take(2).toHList[Int::Int::HNil]
    val long_b  = Stream.from(7).take(5).toHList[Int::Int::Int::Int::Int::HNil]
    

    toHList returns an Option[HList] so we'll map over the results to extract the HList to be zipped.

    short_b.map(a zip _)  // 2 element result
    //res0: Option[(Double, Int) :: (Boolean, Int) :: HNil] =
    // Some((1.3,1) :: (true,2) :: HNil)
    
    long_b.map(a zip _)  // 3 element result
    //res1: Option[(Double, Int) :: (Boolean, Int) :: (String, Int) :: HNil] =
    // Some((1.3,7) :: (true,8) :: (z,9) :: HNil)