如何映射Nat的无形HList

Mol*_*daa 4 scala shapeless

我有一个Nat的HList,我想要映射它

object NatToString extends Poly1 {
    implicit def caseNat = at[Nat](_.toString)
}

val list = _5 :: _3 :: HNil
list.map(NatToString) 
Run Code Online (Sandbox Code Playgroud)

此代码不编译并抛出:

找不到参数映射器的隐含值:
shapeless.ops.hlist.Mapper [Main.Nat_to_String.type,shapeless.:: [shapeless.Nat._5,shapeless.:: [shapeless.Nat._3,shapeless.HNil]] ]

但是,如果我用Int(或String,或List等)代替Nat做同样的事情,它就完美无缺.

我如何映射Nat的HList?

Tra*_*own 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)
}
Run Code Online (Sandbox Code Playgroud)

现在fooIdentity(foo)将编译,但fooIdentity(bar)不会.

在您的情况下,HList静态类型的成员为_5_3.这些是子类型Nat,但NatToString并不关心,因为它唯一的情况是寻找静态类型的东西Nat.

诀窍就是在案例中添加一个类型参数:

object NatToString extends Poly1 {
  implicit def caseNat[N <: Nat] = at[N](_.toString)
}
Run Code Online (Sandbox Code Playgroud)

你会发现,一般来说,Nat直接使用并不是你想要的 - 你几乎总是想要一个特定的子类型.