Can shapeless Record type be used as a Poly1?

限于喜欢 提交于 2021-02-11 12:21:58

问题


Assuming if I have the following Record typed data, and a hlist of keys:

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

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

And I want to extract values in rr for each key in hh, then combine them into a type level object, eventually yielding:

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

How this can be achieved with least amount of code? I could obviously write a inductively-summoned implicit function but it seems to be overkill


回答1:


Firstly, you have typos. ->> should be instead of ->.

Secondly, val hh = "c" :: "b" :: HNil doesn't have type "c" :: "b" :: HNil, it has type String :: String :: HNil instead (so you're loosing compile-time information about keys). If you want hh to have type "c" :: "b" :: HNil (so that values with such keys can be extracted from rr) then you should use .narrow

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

Thirdly, if you want to extract a value from a record by a key you should use type class shapeless.ops.record.Selector. If you want to extract several values by several keys you should use type class shapeless.ops.record.SelectAll. There is extension method get/apply defined via Selector in shapeless.record._ but I can't find the one defined via SelectAll so you can define it yourself similarly to 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


来源:https://stackoverflow.com/questions/66020239/can-shapeless-record-type-be-used-as-a-poly1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!