在类中使用ReplaceAt

时间:2017-09-27 23:08:55

标签: scala generics shapeless

我正在为Shapeless HList构建一个包装器,我想使用updatedAt函数来更新HList中的值,但我似乎无法得到正确的含义。这些是我认为最接近工作解决方案的两个版本:

class Data[L <: HList](val hl: L) {

  def updatedAtV1[V](n : Nat, value : V)(implicit 
         replacer : ReplaceAt[L, n.N, V]) : replacer.Out = replacer(hl, value)

  def updatedAtV2[V, Out <: HList](n : Nat, value : V)(implicit
         replacer : ReplaceAt.Aux[L, n.N, V, (V, Out)]) : Out = replacer(hl, value)._2

}

V1编译,但因为它返回Tuple我无法将其强制转换为Tuple类型,因此我无法获得replacer(hl, value)._2元素。在V2中,编译器无法解析Out类型。

请注意,如果值与其替换的类型相同,则V2可以正常工作,但如果它是不同的类型则会失败。

1 个答案:

答案 0 :(得分:2)

由于隐含的原因,它不适用于不同的类型:

ReplaceAt.Aux[L, n.N, V, (V, Out)] 

您已告知要在V处放置n类型的值,并将V退出HList。您可以通过引入额外的类型参数来修复它:

def updatedAtV3[V, W, Out <: HList](n : Nat, value : V)(implicit
  replacer : ReplaceAt.Aux[L, n.N, V, (W, Out)]) : Out = replacer(hl, value)._2

W - 列表中已有的元素 - 可以是任何东西(它将从隐式参数中推断出来),所以一切正常:

new Data(1 :: HNil).updatedAtV3(0, 42) == 42 :: HNil    
new Data(1 :: HNil).updatedAtV3(0, "foo") == "foo" :: HNil