我有一个Nat的HList,我想映射到它上面
object NatToString extends Poly1 {
implicit def caseNat = at[Nat](_.toString)
}
val list = _5 :: _3 :: HNil
list.map(NatToString)
此代码不能编译并抛出:
无法找到参数映射器的隐式值:
shapeless.ops.hlist.Mapper [Main.Nat_to_String.type无形。::[shapeless.Nat._5无形。::[shapeless.Nat._3, shapeless.HNil]]]
但是如果我用Int(或String,或List,等等)代替Nat做同样的事情,它就会完美地工作。
如何映射Nat的HList ?
问题是Poly1.Case
在其类型参数中不是协变的。考虑以下内容:
trait Foo
trait Bar extends Foo
val foo = new Foo {}
var bar = new Bar {}
object fooIdentity extends Poly1 {
implicit def caseFoo = at[Foo](identity)
}
现在fooIdentity(foo)
可以编译,但fooIdentity(bar)
不能。
在您的示例中,HList
的成员静态类型为_5
和_3
。这些是Nat
的子类型,但NatToString
并不关心,因为它唯一的情况是寻找静态类型为Nat
的东西。
object NatToString extends Poly1 {
implicit def caseNat[N <: Nat] = at[N](_.toString)
}
您会发现通常直接使用Nat
并不是您想要的—您几乎总是需要一个特定的子类型。