HList转换Out类型

时间:2017-11-02 01:06:32

标签: scala shapeless

我在HList上创建了一个可以附加HLists的包装器。它的定义如下:

class HListWrapper[L <: HList](val hl: L) {
  def append[V, Out <: HList](k: Witness, v: V)(implicit updater: Updater.Aux[L, FieldType[k.T, V], Out],
                                                lk: LacksKey[L, k.T]): HListWrapper[Out] = {
    new HListWrapper(updater(hl, field[k.T](v)))
  }
}
object HListWrapper {
  def apply[P <: Product, L <: HList](p: P)(implicit gen: LabelledGeneric.Aux[P, L]) =
    new HListWrapper(gen.to(p))
}

它使用如下:

case class CC(i: Int, ii: Int)
val cc = CC(100, 1000)
val hl = HListWrapper(cc)
hl.append('iii, 10000)

但是当我尝试将HListWrapper放在另一个函数中来捕获Out的类型时,编译器似乎无法解析转换的最终类型(失败并出现类型不匹配错误):< / p>

def cctohlist[Out <: HList]: CC => HListWrapper[Out] = {
  m => {
    val hl = HListWrapper(m)
    hl.append('iii, 10000)
  }
}

创建cctohlist方法的主要原因是在追加后获取HList的类型。这有可能实现吗?

1 个答案:

答案 0 :(得分:1)

以下代码有效:

def cctohlist: CC => HListWrapper[Record.`'i -> Int, 'ii -> Int, 'iii -> Int`.T] = {
    m => {
      val hl = HListWrapper(m)
      hl.append('iii, 10000)
    }
  }

写作时

def cctohlist[Out <: HList]: CC => HListWrapper[Out] = ???

这意味着我可以申请cctohlist[Int :: String :: Boolean :: HNil]并拥有CC => HListWrapper[Int :: String :: Boolean :: HNil]或者我可以申请cctohlist[AnyVal :: AnyRef :: Any :: HNil]并拥有CC => HListWrapper[AnyVal :: AnyRef :: Any :: HNil]等。显然情况并非如此。

这是通用的:

def cctohlist[P <: Product, L <: HList, Out <: HList](m: P)(implicit
  gen: LabelledGeneric.Aux[P, L],
  updater: Updater.Aux[L, FieldType[Witness.`'iii`.T, Int], Out],
  lk: LacksKey[L, Witness.`'iii`.T]
  ): HListWrapper[Out] = {
    val hl = HListWrapper(m)
    hl.append('iii, 10000)
  }

cctohlist(cc)