Most likely, the only thing you can do is define individual cases for Some and for None :
trait a extends Poly1 { implicit def default[T] = at[T](_ :: HNil) } object f extends a { implicit def caseSome[T] = at[Some[T]](_.get :: HNil) implicit def caseNone = at[None.type](_ => HNil) }
This also means that you cannot use the generic Option type in types, at compile time it should be known whether each element is Some or None :
scala> (Some(A(1)) :: A(2) :: Some(B("two")) :: None :: HNil) flatMap f res1: shapeless.::[A,shapeless.::[A,shapeless.::[B,shapeless.HNil]]] = A(1) :: A(2) :: B(two) :: HNil
This difference determines the type of expression obtained: Some(1) :: HNil flatMap f will be of type ::[Int, HNil] , but None :: HNil flatMap f will be of type simply HNil .
This type of type information cannot be computed at compile time from a simple Option s: should (x: Option[T]) :: HNil flatMap f is of type ::[T, HNil] or HNil ? We do not know until we actually run the program and see what the value of x .
I'm not sure if there is any smart way to do this anyway and get an opaque HList , but at this point you will refuse accurate information about the type of each item and the length of the list and can also do it to a normal List (and maybe use cast from formless later if you know which type will get the final result)
source share