带有选项的无形平面图 HList 产生 HList
Shapeless flatmap HList with Option yielding HList
鉴于以下情况
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
如何获得以下内容?
A(1) :: A(2) :: B("two") :: HNil
我的尝试低于
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)
}
适用于地图
h map f
> A(1) :: HNil :: A(2) :: HNil :: B(two) :: HNil :: HNil :: HNil
但 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]]]]]
很可能您唯一能做的就是为 Some
和 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)
}
这也意味着你不能在类型中使用泛型 Option
,必须 在编译时知道每个元素是否是 Some
或 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
此区别定义了结果表达式的类型:Some(1) :: HNil flatMap f
的类型为 ::[Int, HNil]
,而 None :: HNil flatMap f
的类型仅为 HNil
。
这种类型信息无法在编译时通过简单的 Option
s 计算出来:(x: Option[T]) :: HNil flatMap f
应该具有类型 ::[T, HNil]
还是 HNil
?我们不知道,直到我们实际 运行 程序并查看 x
的值是什么。
我不确定是否有一些聪明的方法可以做到这一点并得到一个不透明的 HList
,但到那时你将放弃关于每个元素和列表长度的确切类型信息和也可以将其转换为正常的 List
(如果您知道最终结果的确切类型,稍后可以使用 shapeless 中的 cast
)
鉴于以下情况
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
如何获得以下内容?
A(1) :: A(2) :: B("two") :: HNil
我的尝试低于
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)
}
适用于地图
h map f
> A(1) :: HNil :: A(2) :: HNil :: B(two) :: HNil :: HNil :: HNil
但 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]]]]]
很可能您唯一能做的就是为 Some
和 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)
}
这也意味着你不能在类型中使用泛型 Option
,必须 在编译时知道每个元素是否是 Some
或 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
此区别定义了结果表达式的类型:Some(1) :: HNil flatMap f
的类型为 ::[Int, HNil]
,而 None :: HNil flatMap f
的类型仅为 HNil
。
这种类型信息无法在编译时通过简单的 Option
s 计算出来:(x: Option[T]) :: HNil flatMap f
应该具有类型 ::[T, HNil]
还是 HNil
?我们不知道,直到我们实际 运行 程序并查看 x
的值是什么。
我不确定是否有一些聪明的方法可以做到这一点并得到一个不透明的 HList
,但到那时你将放弃关于每个元素和列表长度的确切类型信息和也可以将其转换为正常的 List
(如果您知道最终结果的确切类型,稍后可以使用 shapeless 中的 cast
)