Scala,将KList的类型参数作为HList获取

J P*_*lar 9 scala shapeless

假设我有一个abitrary KList,为了参数的缘故,它有类型构造函数Option [_],即;

type Example = Option[Int] :: Option[String] :: HNil
Run Code Online (Sandbox Code Playgroud)

有没有办法可以检索由类型参数组成的Hlist?

type Params = Int :: String :: HNil
Run Code Online (Sandbox Code Playgroud)

因此,例如,我可能能够定义某种任意的getOrElse方法

getOrElse(ex:Example, default:Params):Params
Run Code Online (Sandbox Code Playgroud)

现在我正在寻找可能具有这种形式的东西(或类似我建议的类型结构可能不可行).

case class MyOptionList[L <: HList](maybes:L) {
  type Concrete = {somehow the hlist params types as an Hlist}
  def getOrElse(default:Concrete):Concrete = ???

}
Run Code Online (Sandbox Code Playgroud)

Tra*_*own 7

我不是Miles,但是有可能用Shapeless's完成你想要做的事情Comapped:

import shapeless._, ops.hlist.Comapped

case class MyOptionList[L <: HList, C <: HList](maybes: L)(
  implicit val comapped: Comapped.Aux[L, Option, C]
) {
  def getOrElse(default: C): C = default // Not a useful implementation
}
Run Code Online (Sandbox Code Playgroud)

然后:

scala> val x: Int :: HNil = MyOptionList(Option(1) :: HNil).getOrElse(2 :: HNil)
x: shapeless.::[Int,shapeless.HNil] = 2 :: HNil
Run Code Online (Sandbox Code Playgroud)

请注意,在某些情况下,将约束放在方法上会更方便:

case class MyOptionList[L <: HList](maybes: L) {
  def getOrElse[C <: HList: ({ type l[x] = Comapped.Aux[L, Option, x] })#l](
    default: C
  ): C = default
}
Run Code Online (Sandbox Code Playgroud)

这里的用法是相同的,但是在case类上没有额外的type参数.如果要使用此方法但限制MyOptionList禁止非Option成员的创建,则可以L <: HList: *->*[Option]#?在其类型参数列表中使用.