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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With