2014-12-13 4 views
8

Я пытаюсь параметризовать метод, который должен работать на общий тип A, для которого можно получить LabelledGeneric. Вот наивный подходПередайте параметр типа, который будет использоваться как аргумент LabelledGeneric

case class Foo(bar: String, baz: Boolean) 

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

val myThingy = params(Foo) 

Конечно, основной макрос жалуется. Он не знает достаточно о A:

типа А не является классом или черта


Итак, я пытался иметь LabelledGeneric вывод

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

это кажется для работы, но тип Repr, как известно, не является HList.

аргументы типа [lbl.Repr] не соответствуют методу применить оценки параметров'S типа [L <: shapeless.HList]


Хорошо, давайте попробуем быть более точным

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

Теперь Repr определенно является HList, но все же Keys не может решить свои проблемы

не может найти неявное значение для значений параметров: shapeless.ops.record.Values ​​[lbl.Repr]


последняя попытка, давайте стараться иметь все, что нужно вычислить неявно

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

Еще не повезло, по-видимому, первый неявный не может не быть решены на месте вызова

мог не т найти неявное значение для параметра LBL: shapeless.LabelledGeneric.Aux [example.Main.Foo.type, Repr]

[ошибка] Титулы (Foo)

Ясно, что все из этой машины работает, когда речь идет о непосредственно с конкретным типом, например

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

Я явно отсутствует необходимый набор доработок на мой тип в подписи метода, но я могу получить мою голову вокруг того, что происходит здесь. Есть идеи?

+0

Не могли бы вы пометить это языком? –

+0

@ 500-InternalServerError конечно, мой плохой. Done –

+0

@GabrielePetronella приятно объяснить, я немного разочарован, чтобы найти этот пост SO после прохождения полдня, чтобы узнать, что вы уже объяснили. – crak

ответ

4

Последний вариант со всем вычисленным неявно работает для меня,

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 

(типа результата Опущенного для удобства чтения).

+0

О, глупый я. Ошибка заключалась в создании конструктора 'Foo', а не экземпляра. Есть ли способ сделать вывод типа с использованием метода применения Foo? Я хотел бы получить что-то вроде 'params (Foo)' –

+0

Имея 'params (Foo)' работу, возможно, но довольно неудобно. В контексте, 'params (Foo)' действительно намного лучше, чем 'params [Foo]'? –

+0

Я работаю над настраиваемой инструкцией по распылению , поэтому в конечном итоге мне нужно будет использовать метод «как» с (Foo) в моей реализации, поэтому мне нужно передать конструктор вниз –

Смежные вопросы