shapeless Record 类型可以用作 Poly1 吗?- 第2部分 [英] Can shapeless Record type be used as a Poly1? - Part 2

查看:52
本文介绍了shapeless Record 类型可以用作 Poly1 吗?- 第2部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为我没有从第 1 部分得到答案:

Since I didn't get an answer from the Part 1:

shapeless Record 类型可以用作 Poly1 吗?

我认为无形中不存在此功能.所以我决定自己的命运,自己写一篇:

I assume this feature doesn't exist in shapeless. So I decided own my fate and to write one myself:

  import shapeless.record._

  case class GetV[H <: HList](hh: H) extends Poly1 {

    implicit def getter[S](
        implicit
        ev: Selector[H, S]
    ): Case.Aux[S, ev.Out] = at[S] { s =>
      val w = Witness(s)
      val _ev = ev.asInstanceOf[Selector[H, w.T]]

      val v = hh.apply(w)(_ev)
      v.asInstanceOf[ev.Out]
    }
  }

它按预期工作,唯一的问题是对 asInstanceOf 的 2 次调用,我认为这是一种不安全的黑客攻击,可以规避类型检查器在单例类型上的陷阱.应该做些什么来改进它?

It works as anticipated, the only problems are 2 invocation of asInstanceOf which I consider to be an unsafe hack to circumvent typechecker's pitfall on singleton types. What should be done to improve it?

如果你想知道它的能力,这是我的测试代码:

In case you want to know its capability, this is my test code:

  import shapeless.syntax.singleton._

  val record = ("a" ->> 1) ::
    ("b" ->> "x") ::
    HNil

  it("getV") {

    object get extends RecordUtils.GetV(record)

    assert(get.apply("a".narrow) == 1)
    assert(get("b".narrow) == "x")
  }

UPDATE 1:这只是我观察到的所有问题之一,如果我将测试用例更改为等效的内容:

UPDATE 1: this is just one of all the problems I have observed, if I change the test case into something equivalent:

  it("getV") {

    // object get extends RecordUtils.GetV(record) <----- should be the same
    val get = RecordUtils.GetV(record)

    assert(get.apply("a".narrow) == 1)
    assert(get("b".narrow) == "x")
  }

它破坏了编译:

[Error] .../RecordUtilsSpec.scala:19: could not find implicit value for parameter cse: shapeless.poly.Case[get.type,String("a") :: shapeless.HNil]
[Error] .../RecordUtilsSpec.scala:20: could not find implicit value for parameter cse: shapeless.poly.Case[get.type,String("b") :: shapeless.HNil]
two errors found

两个测试用例有什么区别?val/object 是否都获得了不稳定的路径,因此它们的依赖类型具有局部作用域?

What's the difference between 2 test cases? Are val/object get both unstable paths so their dependent types have local scope?

推荐答案

请参阅我对第 1 部分的回答.

Please see my answer for Part 1.

关于第 2 部分,您可以更轻松地定义 implicit def getter 而无需 asInstanceOf 使用您已经拥有的类型类作为隐式参数(而不是扩展方法和 见证)

Regarding Part 2, you can define implicit def getter without asInstanceOf much easier using type class that you already have as an implicit parameter (instead of extension method and Witness)

case class GetV[H <: HList](hh: H) extends Poly1 {    
  implicit def getter[S](implicit
    ev: Selector[H, S]
  ): Case.Aux[S, ev.Out] = at[S] { _ =>
    ev(hh)
  }
}

关于更新,Shapeless 中常见的情况是多态函数应该通过对象而不是 val 来定义.否则你必须导入隐式

Regarding update, it's common situation in Shapeless that polymorphic functions should be defined via objects rather than vals. Otherwise you have to import implicits

val get = GetV(record)
import get._

这篇关于shapeless Record 类型可以用作 Poly1 吗?- 第2部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆