HList lifeless tablet with HList option

Given the following

case class A(value:Int) case class B(value:String) val h:Option[A] :: A :: Option[B] :: Option[A] :: HNil = Some(A(1)) :: A(2) :: Some(B("two")) :: (None:Option[B]) :: HNil 

How can I get the following?

 A(1) :: A(2) :: B("two") :: HNil 

My attempt below

 trait a extends Poly1 { implicit def any[T] = at[T](_ :: HNil) } object f extends a { implicit def some[T] = at[Option[T]](t => if (t.isDefined) t.get :: HNil else HNil) } 

works for the card

 h map f > A(1) :: HNil :: A(2) :: HNil :: B(two) :: HNil :: HNil :: HNil 

but crashing for flatMap

 h flatMap f > could not find implicit value for parameter mapper: shapeless.ops.hlist.FlatMapper[f.type,shapeless.::[Option[A],shapeless.::[A,shapeless.::[Option[B],shapeless.::[Option[B],shapeless.HNil]]]]] 
+4
source share
1 answer

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)

+1
source

Source: https://habr.com/ru/post/1268581/


All Articles