如何映射Nat的无形HList

时间:2014-07-23 19:56:42

标签: scala shapeless

我有一个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?

1 个答案:

答案 0 :(得分:5)

问题是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直接合作并不是您想要的 - 您几乎总是想要一个特定的子类型。