在scala2.13中,为什么有时不可能显式调用类型类



以下是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[_]的类型类?

您丢失了类型精化。更换

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

编译。

在scala中,链接用类型类定义的函数的最简单方法是什么?哪个输出类型依赖于它?

最新更新