【问题标题】:Shapeless flatmap HList with Option yielding HList带有选项产生 HList 的无形平面图 HList
【发布时间】:2015-04-12 16:05:23
【问题描述】:

鉴于以下

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]]]]]

【问题讨论】:

  • 有点不清楚你在问什么。 f 是什么? flatMap 的参数是什么样的?同样,正如定义的 h 将被静态类型化为具有 Some[A] 等元素,这几乎没有用处。

标签: scala shapeless


【解决方案1】:

很可能您唯一能做的就是为SomeNone 定义单独的案例:

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)
}

这也意味着你不能在类型中使用泛型Options,它必须在编译时知道每个元素是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

这种类型信息在编译时无法从简单的Options 中计算出来:(x: Option[T]) :: HNil flatMap f 应该具有::[T, HNil]HNil 类型吗?直到我们实际运行程序并查看x 的值是什么,我们才知道。

我不确定是否有一些聪明的方法可以做到这一点并得到一个不透明的HList,但那时你会放弃关于每个元素和列表长度的确切类型信息,还不如强制转换将其转换为普通的List(如果您知道最终结果的确切类型,则可能稍后使用 shapeless 中的cast

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    相关资源
    最近更新 更多