在 scala 2.13 中,为什么有时无法显式调用类型 class?
In scala 2.13, why is it sometimes impossible to summon type class explicitly?
这是 shapeless 2.3.3 中的一个简单示例:
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") // works fine
// summoning Values[_] type class explicitly, the HList & TypeTag are optional
case class HasValues[T <: HList: TypeTag](v: T) {
def vs(implicit v: Values[T]): Values[T] = v
}
val _vs = HasValues(book).vs
val v2 = book.values(_vs)
assert(v2.head == "Benjamin Pierce") // compilation error!
尽管 v2 在语法上与 v1 相同,但最后一行给出了以下错误:
: could not find implicit value for parameter c: shapeless.ops.hlist.IsHCons[com.tribbloids.spike.shapeless_spike.RecordProblem._vs.Out]
one error found
进一步调查表明符号 v1 的类型层次结构如下所示:
-+ String :: String :: Int :: Double :: shapeless.HNil
: `-+ [ 2 ARGS ] :
: !-+ String .................................................................................................................. [0]
: : !-+ CharSequence
: : : !-+ Object .................................................................................................................. [1]
: : : !-- Any ..................................................................................................................... [2]
: : !-- Comparable[String]
: : : `-+ [ 1 ARG ] :
: : : !-- String .................................................................................................................. [0]
: : !-- java.io.Serializable .................................................................................................... [3]
: !-+ String :: Int :: Double :: shapeless.HNil
: : `-+ [ 2 ARGS ] :
: : !-- String .................................................................................................................. [0]
: : !-+ Int :: Double :: shapeless.HNil
: : : `-+ [ 2 ARGS ] :
: : : !-+ Int
: : : : !-+ AnyVal .................................................................................................................. [4]
: : : : !-- Any ..................................................................................................................... [2]
: : : !-+ Double :: shapeless.HNil
: : : : `-+ [ 2 ARGS ] :
: : : : !-+ Double
: : : : : !-- AnyVal .................................................................................................................. [4]
: : : : !-+ shapeless.HNil
: : : : !-+ shapeless.HList ......................................................................................................... [5]
: : : : !-+ Serializable
: : : : : !-- java.io.Serializable .................................................................................................... [3]
: : : : !-+ Product
: : : : : !-- Equals
: : : : !-- Object .................................................................................................................. [1]
: : : !-- shapeless.HList ......................................................................................................... [5]
: : !-- shapeless.HList ......................................................................................................... [5]
: !-- shapeless.HList ......................................................................................................... [5]
!-- shapeless.HList ......................................................................................................... [5]
但 v2 的类型层次结构省略了大部分信息:
-+ com.tribbloids.spike.shapeless_spike.RecordProblem._vs.Out
!-+ shapeless.HList
!-+ Serializable
: !-+ java.io.Serializable
: !-- Any
!-+ Product
: !-- Equals
!-- Object
这是什么原因,我如何正确地召唤 Value[_] 的 class 类型?
您丢失了类型优化。替换
case class HasValues[T <: HList: TypeTag](v: T) {
def vs(implicit v: Values[T]): Values[T] = v
}
和
case class HasValues[T <: HList: TypeTag](v: T) {
def vs(implicit v: Values[T]): Values.Aux[T, v.Out] = v
}
然后两者
val v2 = book.values
assert(v2.head == "Benjamin Pierce")
和
val v2 = book.values(_vs)
assert(v2.head == "Benjamin Pierce")
编译。
这是 shapeless 2.3.3 中的一个简单示例:
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") // works fine
// summoning Values[_] type class explicitly, the HList & TypeTag are optional
case class HasValues[T <: HList: TypeTag](v: T) {
def vs(implicit v: Values[T]): Values[T] = v
}
val _vs = HasValues(book).vs
val v2 = book.values(_vs)
assert(v2.head == "Benjamin Pierce") // compilation error!
尽管 v2 在语法上与 v1 相同,但最后一行给出了以下错误:
: could not find implicit value for parameter c: shapeless.ops.hlist.IsHCons[com.tribbloids.spike.shapeless_spike.RecordProblem._vs.Out]
one error found
进一步调查表明符号 v1 的类型层次结构如下所示:
-+ String :: String :: Int :: Double :: shapeless.HNil
: `-+ [ 2 ARGS ] :
: !-+ String .................................................................................................................. [0]
: : !-+ CharSequence
: : : !-+ Object .................................................................................................................. [1]
: : : !-- Any ..................................................................................................................... [2]
: : !-- Comparable[String]
: : : `-+ [ 1 ARG ] :
: : : !-- String .................................................................................................................. [0]
: : !-- java.io.Serializable .................................................................................................... [3]
: !-+ String :: Int :: Double :: shapeless.HNil
: : `-+ [ 2 ARGS ] :
: : !-- String .................................................................................................................. [0]
: : !-+ Int :: Double :: shapeless.HNil
: : : `-+ [ 2 ARGS ] :
: : : !-+ Int
: : : : !-+ AnyVal .................................................................................................................. [4]
: : : : !-- Any ..................................................................................................................... [2]
: : : !-+ Double :: shapeless.HNil
: : : : `-+ [ 2 ARGS ] :
: : : : !-+ Double
: : : : : !-- AnyVal .................................................................................................................. [4]
: : : : !-+ shapeless.HNil
: : : : !-+ shapeless.HList ......................................................................................................... [5]
: : : : !-+ Serializable
: : : : : !-- java.io.Serializable .................................................................................................... [3]
: : : : !-+ Product
: : : : : !-- Equals
: : : : !-- Object .................................................................................................................. [1]
: : : !-- shapeless.HList ......................................................................................................... [5]
: : !-- shapeless.HList ......................................................................................................... [5]
: !-- shapeless.HList ......................................................................................................... [5]
!-- shapeless.HList ......................................................................................................... [5]
但 v2 的类型层次结构省略了大部分信息:
-+ com.tribbloids.spike.shapeless_spike.RecordProblem._vs.Out
!-+ shapeless.HList
!-+ Serializable
: !-+ java.io.Serializable
: !-- Any
!-+ Product
: !-- Equals
!-- Object
这是什么原因,我如何正确地召唤 Value[_] 的 class 类型?
您丢失了类型优化。替换
case class HasValues[T <: HList: TypeTag](v: T) {
def vs(implicit v: Values[T]): Values[T] = v
}
和
case class HasValues[T <: HList: TypeTag](v: T) {
def vs(implicit v: Values[T]): Values.Aux[T, v.Out] = v
}
然后两者
val v2 = book.values
assert(v2.head == "Benjamin Pierce")
和
val v2 = book.values(_vs)
assert(v2.head == "Benjamin Pierce")
编译。