【问题标题】:Can shapeless Record type be used as a Poly1?无形记录类型可以用作 Poly1 吗?
【发布时间】:2021-05-07 06:07:07
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: scala shapeless polymorphic-functions


    【解决方案1】:

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

    其次,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。在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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-27
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 1970-01-01
      • 2014-07-25
      • 1970-01-01
      • 2011-09-15
      相关资源
      最近更新 更多