0

假设我是否有以下 Record 类型的数据和一个键列表:

    val rr = ("a" ->> 1) ::
      ("b" -> "s") ::
      ("c" -> 3) ::
      HNil

val hh = "c" :: "b" :: HNil

我想为 inrr中的每个键提取值hh,然后将它们组合成一个类型级别的对象,最终产生:

(3: Int) :: ("s": String) :: HNil

如何用最少的代码实现这一点?我显然可以写一个归纳调用的隐式函数,但这似乎有点过头了

4

1 回答 1

1

首先,你有错别字。->>应该代替->.

其次,val hh = "c" :: "b" :: HNil没有 type "c" :: "b" :: HNil,它有 type String :: String :: HNil(所以你失去了关于键的编译时信息)。如果您想要hh类型"c" :: "b" :: HNil(以便可以从中提取具有此类键的值rr),那么您应该使用.narrow

type hht = "c" :: "b" :: HNil
val hh: hht = "c".narrow :: "b".narrow :: HNil

第三,如果你想通过一个键从记录中提取一个值,你应该使用 type class shapeless.ops.record.Selector。如果你想通过几个键提取多个值,你应该使用 type class shapeless.ops.record.SelectAll。有扩展方法get/apply通过Selectorin定义,shapeless.record._但我找不到定义的方法,SelectAll因此您可以自己定义它,类似于get/apply

implicit class RecordOps[L <: HList](val l : L) {
  def getAll[K <: HList](k: K)(implicit selector: SelectAll[L, K]): selector.Out = 
    selector(l)
  def getAllByType[K <: HList](implicit selector: SelectAll[L, K]): selector.Out = 
    selector(l)
}

rr.getAll(hh) // 3 :: s :: HNil
rr.getAllByType[hht] // 3 :: s :: HNil
于 2021-02-04T15:14:34.467 回答