【问题标题】:In scala 2.13, why is it sometimes impossible to summon type class explicitly? - Part 2在 scala 2.13 中,为什么有时无法显式调用类型类? - 第2部分
【发布时间】:2021-04-14 12:13:03
【问题描述】:

这是In scala 2.13, why is it sometimes impossible to summon type class explicitly?的后续问题:

以下代码可以正常编译:

  import shapeless._
  import record._
  import syntax.singleton._

  val book =
    ("author" ->> "Benjamin Pierce") ::
      ("title" ->> "Types and Programming Languages") ::
      ("id" ->> 262162091) ::
      ("price" ->> 44.11) ::
      HNil

  val v1 = book.values

  assert(v1.head == "Benjamin Pierce")

  case class HasValues[T <: HList: TypeTag](v: T) {

//    def vs(implicit v: Values[T]) = v // doesn't work
    def vs(implicit v: Values[T]): Values.Aux[T, v.Out] = v // works
  }

  val _vs = HasValues(book).vs

  val v2 = book.values(_vs)

  assert(v2.head == "Benjamin Pierce")

虽然以下代码在编译时和运行时语法相同,但编译失败:

  import shapeless._
  import record._
  import syntax.singleton._

  val book =
    ("author" ->> "Benjamin Pierce") ::
      ("title" ->> "Types and Programming Languages") ::
      ("id" ->> 262162091) ::
      ("price" ->> 44.11) ::
      HNil

  val v1 = book.values

  assert(v1.head == "Benjamin Pierce")

  case class HasValues[T <: HList: TypeTag](v: T) {

    type TT = T
  }

  val hv = HasValues(book)

  val _vs = implicitly[Values[hv.TT]]
  val _vs2: Values.Aux[hv.TT, _vs.Out] = _vs

  val v2 = book.values(_vs2)

  assert(v2.head == "Benjamin Pierce")

结果:

[Error] /home/peng/git-spike/scalaspike/common/src/test/scala/com/tribbloids/spike/shapeless_spike/RecordProblem2.scala:41: could not find implicit value for parameter c: shapeless.ops.hlist.IsHCons[com.tribbloids.spike.shapeless_spike.RecordProblem2._vs2.Out]
one error found

此外,以下行似乎非常样板。理想情况下,我认为编译器应该能够对自己进行改进,考虑到这完全是一个向上的选择:

  val _vs = implicitly[Values[hv.TT]]
  val _vs2: Values.Aux[hv.TT, _vs.Out] = _vs

为什么第二个编译失败,此外,如何摆脱样板鸭类型声明? (当然,不用修改HasValues类的签名)

【问题讨论】:

    标签: scala typeclass shapeless scala-2.13


    【解决方案1】:

    implicitly 可能会破坏类型优化。请改用shapeless.the

    代码

    val hv = HasValues(book)
    
    val _vs = the[Values[hv.TT]]
    val _vs2: Values.Aux[hv.TT, _vs.Out] = _vs
    
    val v2 = book.values(_vs2)
    
    assert(v2.head == "Benjamin Pierce")
    

    编译。

    https://typelevel.org/blog/2014/01/18/implicitly_existential.html

    Scala compiler expand types

    还有

    val hv = HasValues(book)
    
    val _vs2 = the[Values[hv.TT]]
    
    val v2 = book.values(_vs2)
    
    assert(v2.head == "Benjamin Pierce")
    

    val hv = HasValues(book)
    
    val v2 = book.values
    
    assert(v2.head == "Benjamin Pierce")
    

    编译。

    还要注意你可以替换

    def vs(implicit v: Values[T]): Values.Aux[T, v.Out] = v
    

    def vs(implicit v: Values[T]): v.type = v
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-21
      • 1970-01-01
      • 2021-03-06
      相关资源
      最近更新 更多