无形记录类型可以用作 Poly1 吗?
Can shapeless Record type be used as a Poly1?
假设我有以下 Record 类型的数据和一个 hlist 键:
val rr = ("a" ->> 1) ::
("b" -> "s") ::
("c" -> 3) ::
HNil
val hh = "c" :: "b" :: HNil
我想为 hh
中的每个键提取 rr
中的值,然后将它们组合成一个类型级对象,最终产生:
(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
第三,如果你想通过一个键从记录中提取一个值,你应该使用类型 class shapeless.ops.record.Selector
。如果你想通过几个键提取多个值,你应该使用类型 class shapeless.ops.record.SelectAll
。在 shapeless.record._
中通过 Selector
定义了扩展方法 get
/apply
但我找不到通过 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
假设我有以下 Record 类型的数据和一个 hlist 键:
val rr = ("a" ->> 1) ::
("b" -> "s") ::
("c" -> 3) ::
HNil
val hh = "c" :: "b" :: HNil
我想为 hh
中的每个键提取 rr
中的值,然后将它们组合成一个类型级对象,最终产生:
(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
第三,如果你想通过一个键从记录中提取一个值,你应该使用类型 class shapeless.ops.record.Selector
。如果你想通过几个键提取多个值,你应该使用类型 class shapeless.ops.record.SelectAll
。在 shapeless.record._
中通过 Selector
定义了扩展方法 get
/apply
但我找不到通过 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