将无形可扩展记录传递给函数(续)

 我叫柒薇安2001 发布于 2023-02-13 16:10

考虑到这个问题:将无形可扩展记录传递给函数,Travis的答案显示,将可扩展记录作为参数的每个函数都必须具有隐式选择器作为参数.我想知道如果我们有很多这样的功能,是否可以将这些声明分解.例如:

val w1 = Witness("foo1")
val w2 = Witness("foo2")
val w3 = Witness("foo3")
//Here some "magical" declarations avoiding to declara selectors in fun1, fun2, fun3 below

 def fun1[L <: HList](xs: L) = ... //Access to foo1, foo2, foo3
 def fun2[L <: HList](xs: L) = ... //Access to foo1, foo2, foo3
 def fun3[L <: HList](xs: L) = ... //Access to foo1, foo2, foo3

谢谢

伯努瓦

编辑12月10日

在尝试答案的代码时,会出现两个问题:

    没有告知关于与foo1,foo2,foo3相关的数据的真实类型:因此,像fun1这样的函数不能使用与这些类型相关联的任何方法.例如,即使foo3是Double,它也不能采用它的平方根.

    如果我有打电话( "foo1" - >> "你好")FUN1 ::( "foo2的" - > 1)::( "foo3" - >> 1.2)::抗扰度逻辑,结果是(你好,1,1.2 )与式(selectors.s1.Out,selectors.s2.Out,selectors.s3.Out)如果我试图加1的最后一个值(1.2),斯卡拉抱怨说,它不能添加一个Int和选择. s3.Out;但如果我写:

      val x = fun1(("foo1"->> "hello") :: ("foo2" -> 1)::("foo3" ->> 1.2)::HNil)
    

    我可以写:

      x._3 == 1.2
    

    和斯卡拉的答案是真的!

我试图以这种方式修改代码,跳转类型将被传播,但它不能解决问题.我甚至不能用(foo1 - >>"hello")::(foo2 - > 1)::(foo3 - >> 1.2):: HNil作为参数调用fun1:

object foo1 extends FieldOf[String]
object foo2 extends FieldOf[Int]
object foo3 extends FieldOf[Double]

val w1 = Witness(foo1)
val w2 = Witness(foo2)
val w3 = Witness(foo3)

case class HasMyFields[L <: HList](implicit
  s1: Selector[L, w1.T],
  s2: Selector[L, w2.T],
 s3: Selector[L, w3.T]
 )

 object HasMyFields {
    implicit def make[L <: HList](implicit
    s1: Selector[L, w1.T],
    s2: Selector[L, w2.T],
    s3: Selector[L, w3.T]
  ) = HasMyFields[L]
}
 def fun1[L <: HList](xs: L)(implicit selectors: HasMyFields[L]) = {
   import selectors._
   (xs(foo1), xs(foo2), xs(foo3))
 }

有没有办法进步?

伯努瓦

1 个回答
  • 您可以定义自己的类型类以收集记录包含所需字段的证据:

    import shapeless._, ops.record.Selector, record._, syntax.singleton._
    
    val w1 = Witness("foo1")
    val w2 = Witness("foo2")
    val w3 = Witness("foo3")
    
    case class HasMyFields[L <: HList](implicit
      s1: Selector[L, w1.T, String],
      s2: Selector[L, w2.T, Int],
      s3: Selector[L, w3.T, Double]
    )
    
    object HasMyFields {
      implicit def make[L <: HList](implicit
        s1: Selector[L, w1.T, String],
        s2: Selector[L, w2.T, Int],
        s3: Selector[L, w3.T, Double]
      ) = HasMyFields[L]
    }
    

    然后,例如:

    def fun1[L <: HList](xs: L)(implicit selectors: HasMyFields[L]) = {
      import selectors._
    
      (xs("foo1"), xs("foo2"), xs("foo3"))
    }
    

    它仍然有点冗长,特别是因为导入是必要的,但远不如单独将所有选择器作为隐式参数.

    2023-02-13 16:12 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有