在 scala 2.13 中,为什么有时无法显式调用类型类?- 第2部分 [英] In scala 2.13, why is it sometimes impossible to summon type class explicitly? - Part 2

查看:50
本文介绍了在 scala 2.13 中,为什么有时无法显式调用类型类?- 第2部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是在 scala 2.13 中,为什么有时无法显式调用类型类?:

以下代码可以正常编译:

The following code can compile properly:

  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")

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

While the following code, which is syntactically identical in both compile time and run time, failed the compilation:

  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

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

In addition, the following line seems to be very boilerplate-y. Ideally I think the compiler should be able to figure out the refinement on itself, considering that this is totally an upcast:

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

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

Why the second one failed the compilation, and furthermore, how to get rid of that boilerplate duck type declaration? (Of course, without modifying the signature of the class HasValues)

推荐答案

隐式 可能会破坏类型细化.改用 shapeless.the.

implicitly can corrupt type refinements. Use shapeless.the instead.

代码

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 编译器扩展类型

还有

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

这篇关于在 scala 2.13 中,为什么有时无法显式调用类型类?- 第2部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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