shapeless Record 类型可以用作 Poly1 吗?

问题描述

假设我有以下记录类型的数据和一个键列表:

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

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

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

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

如何用最少的代码实现这一点?我显然可以写一个归纳召唤的隐式函数,但它似乎有点矫枉过正

解决方法

首先,你有错别字。 -> 应该代替 val hh = "c" :: "b" :: HNil

其次,"c" :: "b" :: HNil 没有 String :: String :: HNil 类型,而是 hh 类型(因此您丢失了有关键的编译时信息)。如果您希望 "c" :: "b" :: HNil 具有 rr 类型(以便可以从 .narrow 中提取具有此类键的值),那么您应该使用 type hht = "c" :: "b" :: HNil val hh: hht = "c".narrow :: "b".narrow :: HNil

shapeless.ops.record.Selector

第三,如果你想通过一个键从记录中提取一个值,你应该使用类型类 shapeless.ops.record.SelectAll。如果您想通过多个键提取多个值,您应该使用类型类 getapply 中通过 Selector 定义了扩展方法 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

{{1}}