我在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
的类型。这有可能实现吗?
答案 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)