具有自定义类型绑定的无形映射和子类型多态性

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] 中的 TT <: 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