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

Cos*_*lis 2 polymorphism scala shapeless

试图映射自定义多态类的HList我得到了可怕的"无法找到参数映射器的隐式值"错误.代码示例:

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))
Run Code Online (Sandbox Code Playgroud)

如果L [T]的边界是例如Iterable(参见这个非常相似的问题,解决方案和注释),这可以正常工作.我错过了什么?

Jas*_*r-M 5

出于某种原因,真正的错误被吞噬了.如果你在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)
                                                     ^
Run Code Online (Sandbox Code Playgroud)

问题是Tin和in 中的那个L[T] <: C[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)
                                                     ^
Run Code Online (Sandbox Code Playgroud)

解决方案是绑定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
Run Code Online (Sandbox Code Playgroud)