Kity Cartman
Kity Cartman

Reputation: 896

How to flatten an HLists of HLists

So at runtime I get an Hlist of Hlists which looks like:

(2 :: HNil) :: (1001 :: HNil) :: (1001 :: HNil) :: HNil

Here the type of the resultant Hlist is :

(Int :: HNil) :: (Long :: HNil) :: (Long :: HNil) :: HNil

but this could have been any other type at runtime. For example, it could have been

(Int :: HNil) :: (String :: HNil) :: HNil


Is there a way to flatten this HList like so:
2 :: 1001 :: 1001 :: HNil

with the following type:

Int :: Long :: Long :: HNil

Upvotes: 2

Views: 183

Answers (2)

sortega
sortega

Reputation: 1158

You can use the identity Poly defined by shapeless for conciseness:

import shapeless._
import shapeless.poly.identity

val nestedHList = (2 :: HNil) :: (1001 :: HNil) :: (1001 :: HNil) :: HNil
nestedHList.flatMap(identity)
// 2 :: 1001 :: 1001 :: HNil

Upvotes: 2

Emiliano Martinez
Emiliano Martinez

Reputation: 4133

You can do it applying functional operations to HList. Take a look to how Poly works. First, we declare the Poly for (Int::HNil) and (Long::HNil):

  import shapeless._

  object myPoly extends Poly1 {
    implicit val tupleIntCase: Case.Aux[(Int :: HNil), Int] =
      at(position => position.head)
    implicit val tupleLongCase: Case.Aux[(Long :: HNil), Long] =
      at(position => position.head)
  }

and using the map function you can extract and flatten the HList:

((2 :: HNil) :: (1001L :: HNil) :: (1001 :: HNil) :: HNil).map(myPoly)

It gives the desired result:

2 :: 1001 :: 1001 :: HNil

Note that the resulting type here is:

Int :: Long :: Int :: HNil

Upvotes: 2

Related Questions