具有自定义类型绑定的无形映射和子类型多态性
Shapeless mapping and subtype polymorphism with custom type bound
尝试映射自定义多态的 HList class 我遇到了可怕的 "could not find implicit value for parameter mapper" 错误。代码示例:
import shapeless._
trait SubTrait
case class A() extends SubTrait
case class B() extends SubTrait
case class C[T <: SubTrait](x: T)
object TheMapper extends Poly1 {
implicit def default[T <: SubTrait, L[T] <: C[T]] = at[L[T]](_.x)
}
val ab = C(A()) :: C(B()) :: HNil
println(ab.map(TheMapper))
如果 L[T] 的边界是例如可迭代(参见 this very similar question、解决方案和评论)。我错过了什么?
由于某种原因,真正的错误被吞没了。如果你在 REPL 中一步步编译你会得到这个错误:
error: type arguments [T] do not conform to class C's type parameter bounds [T <: SubTrait]
implicit def default[T <: SubTrait, L[T] <: C[T]] = at[L[T]](_.x)
^
问题是 L[T] <: C[T]
中的 T
与 T <: SubTrait
中的不一样。如果您重命名它,它会变得更具可读性:
scala> object TheMapper extends Poly1 {
| implicit def default[T <: SubTrait, L[x] <: C[x]] = at[L[T]](_.x)
| }
<console>:18: error: type arguments [x] do not conform to class C's type parameter bounds [T <: SubTrait]
implicit def default[T <: SubTrait, L[x] <: C[x]] = at[L[T]](_.x)
^
解决方案是在 x
上设置一个界限。
scala> object TheMapper extends Poly1 {
| implicit def default[T <: SubTrait, L[x <: SubTrait] <: C[x]] = at[L[T]](_.x)
| }
defined object TheMapper
scala> val ab = C(A()) :: C(B()) :: HNil
ab: shapeless.::[C[A],shapeless.::[C[B],shapeless.HNil]] = C(A()) :: C(B()) :: HNil
scala> println(ab.map(TheMapper))
A() :: B() :: HNil
尝试映射自定义多态的 HList class 我遇到了可怕的 "could not find implicit value for parameter mapper" 错误。代码示例:
import shapeless._
trait SubTrait
case class A() extends SubTrait
case class B() extends SubTrait
case class C[T <: SubTrait](x: T)
object TheMapper extends Poly1 {
implicit def default[T <: SubTrait, L[T] <: C[T]] = at[L[T]](_.x)
}
val ab = C(A()) :: C(B()) :: HNil
println(ab.map(TheMapper))
如果 L[T] 的边界是例如可迭代(参见 this very similar question、解决方案和评论)。我错过了什么?
由于某种原因,真正的错误被吞没了。如果你在 REPL 中一步步编译你会得到这个错误:
error: type arguments [T] do not conform to class C's type parameter bounds [T <: SubTrait]
implicit def default[T <: SubTrait, L[T] <: C[T]] = at[L[T]](_.x)
^
问题是 L[T] <: C[T]
中的 T
与 T <: SubTrait
中的不一样。如果您重命名它,它会变得更具可读性:
scala> object TheMapper extends Poly1 {
| implicit def default[T <: SubTrait, L[x] <: C[x]] = at[L[T]](_.x)
| }
<console>:18: error: type arguments [x] do not conform to class C's type parameter bounds [T <: SubTrait]
implicit def default[T <: SubTrait, L[x] <: C[x]] = at[L[T]](_.x)
^
解决方案是在 x
上设置一个界限。
scala> object TheMapper extends Poly1 {
| implicit def default[T <: SubTrait, L[x <: SubTrait] <: C[x]] = at[L[T]](_.x)
| }
defined object TheMapper
scala> val ab = C(A()) :: C(B()) :: HNil
ab: shapeless.::[C[A],shapeless.::[C[B],shapeless.HNil]] = C(A()) :: C(B()) :: HNil
scala> println(ab.map(TheMapper))
A() :: B() :: HNil