Getting elements from an HList

故事扮演 提交于 2019-12-20 21:46:29

问题


I toyed around with HList and the following works as expected:

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

However, I can't get the following piece of code working (let's assume for a moment random access on lists is a smart idea ;-)):

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)

I'd like to have get return an Int and String according to it's parameter. I assume, if possible at all, I have to use Aux or at but I'm not sure how to do this.


回答1:


Try something along these lines,

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

The first crucial difference here is that rather than typing hl as plain HList, which loses all specific information about the types of the elements, we parametrize over the precise type of the argument and preserve its structure as L. The second difference is that we use L to index the implicit At type class instance which is used to perform the indexing in get.

Also note that because there is an implicit conversion from Int literals to Nat's you can write,

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

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


来源:https://stackoverflow.com/questions/35535543/getting-elements-from-an-hlist

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!