Передайте параметр типа, который будет использоваться в качестве аргумента 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

(типы результатов исключены для удобства чтения).

Другие вопросы по тегам