在 scala 2.13 中,为什么有时无法显式调用类型 class? - 第2部分
In scala 2.13, why is it sometimes impossible to summon type class explicitly? - Part 2
这是 的后续问题:
以下代码可以正常编译:
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
为什么第二个编译失败,而且,如何去掉那个样板鸭子类型声明? (当然,不修改签名的class HasValues)
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
还有
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
这是
以下代码可以正常编译:
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
为什么第二个编译失败,而且,如何去掉那个样板鸭子类型声明? (当然,不修改签名的class HasValues)
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
还有
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