2017-03-17 80 views
2

试图映射自定义多态类的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,解决方案和注释)。我错过了什么?

回答

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

的问题是,在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 
+0

请注意,惯例是写本地类型变量小写。 – OlivierBlanvillain

+0

@OlivierBlanvillain哦,好的。我不能说我已经看到这种做法足够坚持承担这一惯例。感谢您指出。 –

+0

使用REPL作为调试器,很好:)谢谢! –