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

时间:2017-03-17 09:36:15

标签: scala polymorphism 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))

如果L [T]的界限是例如,则该方法可以正常工作。 Iterable(请参阅this very similar question,解决方案和评论)。我错过了什么?

1 个答案:

答案 0 :(得分: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)
                                                     ^

问题是T中的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) ^ 不同。如果重命名它会更具可读性:

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

X = [1,2,3,4,5];
Y = [2,2,4,7,1];
Z = [0.96,0.52,0.74,0.10,0.33];