HList 转换 Out 类型

HList transformation Out type

我在 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 的类型时,编译器似乎无法解析转换的最终类型(因类型不匹配错误而失败) :

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

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

以下代码有效:

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)