2016-02-21 11 views
6

Ho giocato in giro con HList e le seguenti opere come previsto:Ottenere elementi da un HList

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

Tuttavia, non posso ottenere il seguente pezzo di codice di lavoro (supponiamo per un momento ad accesso casuale su liste è un'idea intelligente ;-)):

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) 

mi piacerebbe avere get restituire un Int e String in base ad esso del parametro. Presumo, se possibile, che devo usare Aux o at ma non sono sicuro di come farlo.

risposta

4

provare qualcosa in questo senso,

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 

La prima differenza fondamentale qui è che, invece di digitare hl come semplice HList, che perde tutte le informazioni specifiche sui tipi di elementi, abbiamo parametrizzare il tipo preciso dell'argomento e conservare la sua struttura come L. La seconda differenza è che utilizziamo L per indicizzare l'istanza di classe di tipo implicita At che viene utilizzata per eseguire l'indicizzazione in get.

Si noti inoltre che, poiché v'è una conversione implicita da Int letterali a Nat 's si può scrivere,

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

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

Grande! Grazie per la tua biblioteca! – user3127060

Problemi correlati