Передайте параметр типа, который будет использоваться в качестве аргумента LabelledGeneric
Я пытаюсь параметризовать метод, который должен работать с универсальным типом A
для чего 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] не соответствуют границам параметра типа применения метода [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]
[ошибка] params(Foo)
Очевидно, что весь этот механизм работает, когда имеет дело непосредственно с конкретным типом, например,
val lbl = LabelledGeneric[Foo]
val keys = Keys[lbl.Repr].apply
// no problem
Я явно упускаю необходимый набор уточнений для моего типа в сигнатуре метода, но я могу понять, что здесь происходит. Любая идея?
1 ответ
Последний вариант со всем вычисленным неявно работает для меня,
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
(типы результатов исключены для удобства чтения).