2014-12-13 24 views
8

Próbuję sparametryzować metodę, która musi działać na typ ogólny A, dla której można pobrać LabelledGeneric. Oto naiwna metoda:Przekaż parametr typu, który ma być użyty jako argument EtykietyGeneric

Oczywiście, podstawowe makro narzeka. Nie wie wystarczająco dużo o A:

typ A nie jest klasą lub cecha


Więc starałem się mieć LabelledGeneric wywnioskować

def params[A](a: A)(implicit lbl: LabelledGeneric[A]) = { 
    val keys = Keys[lbl.Repr].apply 
    ... 
} 

wydaje do pracy, ale typ Repr nie jest już znany jako HList

typu argumenty [lbl.Repr] nie odpowiadają metody zastosować typ granic parametrów [L <: shapeless.HList]


Ok, spróbujmy dokładniej

def params[A, Repr <: HList](a: A)(implicit lbl: LabelledGeneric.Aux[A, Repr]) = { 
    val keys = Keys[lbl.Repr].apply 
    ... 
} 

teraz Repr jest zdecydowanie HList, ale nadal nie można rozwiązać Keys jego implicits

nie mógł znaleźć ukrytą wartość dla wartości parametrów: shapeless.ops.record.Values ​​[lbl.Repr]


ostatniej próby, spróbujmy się mieć wszystko, czego potrzebuję obliczane w sposób dorozumiany

def params[A, Repr <: HList](a: A)(implicit 
    lbl: LabelledGeneric.Aux[A, Repr], 
    kk: Keys[Repr] 
) = { 
    val keys = kk.apply 
    ... 
} 

Wciąż nie ma szczęścia, pozornie pierwszy niejawna nie mogą być rozwiązane w miejscu połączenia

nie mógł odnaleźć ukrytą wartość parametru LBL: shapeless.LabelledGeneric.Aux [example.Main.Foo.type, Repr]

[Błąd] params (Foo)

Oczywiście to wszystko maszynowych prac, kiedy zajmujących się bezpośrednio z określonym typem, np

val lbl = LabelledGeneric[Foo] 
val keys = Keys[lbl.Repr].apply 
// no problem 

ja wyraźnie brakuje potrzebnej zestaw udoskonaleń w moim typu w podpis metody, ale mogę uzyskać moja głowa wokół tego, co się tutaj dzieje. Dowolny pomysł?

+0

Czy możesz oznaczyć to za pomocą używanego języka? –

+0

@ 500-InternalServerError oczywiście, mój zły. Zrobione –

+0

@GabrielePetronella miło wyjaśnić, jestem trochę zawiedziony, że znajdę ten wpis SO po przejściu przez pół dnia, aby znaleźć to, co już wyjaśniłeś – crak

Odpowiedz

4

Ostatni wariant ze wszystkim, obliczonego w sposób dorozumiany pracuje dla mnie,

scala> import shapeless._, ops.record._ 
import shapeless._ 
import ops.record._ 

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

def params[A, Repr <: HList](a: A) 
    (implicit lbl: LabelledGeneric.Aux[A, Repr], kk: Keys[Repr]) = { 
    val keys = kk.apply 
    keys 
} 

// Exiting paste mode, now interpreting. 

params: ... 

scala> case class Foo(bar: String, baz: Boolean) 
defined class Foo 

scala> params(foo) 
res0: ... = 'bar :: 'baz :: HNil 

(rodzaje wynikowych pomijana dla czytelności).

+0

oh, głuptasie. Błąd polegał na przekazywaniu konstruktora 'Foo' zamiast instancji. Czy istnieje sposób na napędzanie wnioskowania typu przy użyciu metody "Foo' apply"? Chciałbym osiągnąć coś w stylu 'params (Foo)' –

+0

Mając 'params (Foo)' praca jest możliwa, ale dość niezręczna. W kontekście, czy 'params (Foo)' naprawdę znacznie lepiej niż 'params [Foo]'? –

+0

Pracuję nad niestandardową dyrektywą dotyczącą trasowania , więc ostatecznie będę musiał użyć metody "as" z (Foo) w mojej implementacji, dlatego muszę przekazać konstruktorowi w dół –

Powiązane problemy