2016-02-21 7 views
6

I bawił się wokół z HList oraz następujące prace zgodnie z oczekiwaniami:Pierwsze elementy z HList

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

Jednak nie mogę się następujący fragment kodu robocza (załóżmy na chwilę losowego dostępu na listach jest to inteligentny pomysł ;-)):

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) 

Chciałbym mieć get zwracać Int i String według jego parametrów. Zakładam, że jeśli to w ogóle możliwe, muszę użyć Aux lub at, ale nie jestem pewien, jak to zrobić.

Odpowiedz

4

spróbować czegoś wzdłuż tych linii,

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 

Pierwsza zasadnicza różnica jest taka, że ​​zamiast wpisywać hl jako zwykły HList, który traci wszystkie szczegółowe informacje na temat typów elementów, my parametrize nad dokładnego rodzaju argumentu i zachowaj jego strukturę jako L. Druga różnica polega na tym, że używamy L do indeksowania niejawnej instancji klasy typu At, która jest używana do wykonywania indeksowania w get.

Należy również zauważyć, że ponieważ istnieje niejawna konwersja z Int literałów do Nat „s można napisać,

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

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

Great! Dzięki za twoją bibliotekę! – user3127060