从HList获取元素

时间:2016-02-21 11:30:38

标签: scala shapeless

我玩弄了HList,以下工作正如预期的那样:

val hl = 1 :: "foo" :: HNil
val i: Int = hl(_0)
val s: String = hl(_1)

但是,我无法使下面的代码工作(让我们暂时假设列表上的随机访问是一个明智的想法; - )):

class Container(hl: HList) {
    def get(n: Nat) = hl(n)
}

val container = new Container(1 :: "foo" :: HNil)
val i: Int = container.get(_0)
val s: String = container.get(_1)

我希望get根据它的参数返回IntString。我假设,如果可能的话,我必须使用Auxat,但我不知道该怎么做。

1 个答案:

答案 0 :(得分:4)

沿着这些方向尝试一下,

scala> import shapeless._, nat._, ops.hlist._
import shapeless._
import nat._
import ops.hlist._

scala> class Container[L <: HList](hl: L) {
     |   def get(n: Nat)(implicit at: At[L, n.N]): at.Out = hl[n.N]
     | }
defined class Container

scala> val container = new Container(1 :: "foo" :: HNil)
container: Container[shapeless.::[Int,shapeless.::[String,shapeless.HNil]]] = ...

scala> container.get(_0)
res1: Int = 1

scala> container.get(_1)
res2: String = foo

这里的第一个关键区别是,不是输入hl作为普通HList,而是丢失了有关元素类型的所有特定信息,我们对参数的精确类型进行参数化并保留其结构为L。第二个区别是我们使用L索引用于在At中执行索引的隐式get类型类实例。

另请注意,因为您可以编写从Int文字到Nat的隐式转换,

scala> container.get(0)
res3: Int = 1

scala> container.get(1)
res4: String = foo