Pass the type parameter that will be used as the argument LabelledGeneric

I am trying to parameterize a method that should work on a generic type A , for which LabelledGeneric can be obtained. Here's a naive approach

 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) 

Of course, the main macro complains. He does not know enough about A :

type A is not a class or attribute


So, I tried to conclude LabelledGeneric

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

this seems to work, but the Repr type is not known as an HList anymore

arguments of type [lbl.Repr] do not match the method used to restrict the type of parameter [L <: shapeless.HList]


Ok try to be more precise

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

Now Repr definitely an HList , but still Keys cannot solve its implications.

Could not find implicit value for parameter values: shapeless.ops.record.Values ​​[lbl.Repr]


Final attempt, try to have everything I need to compute implicitly

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

Still no luck, obviously the first implicit cannot be resolved on the call site

could not find the implicit value of the lbl parameter: shapeless.LabelledGeneric.Aux [example.Main.Foo.type, Repr]

[error] params (Foo)

Obviously, all this equipment works with direct reference to a specific type, for example

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

I clearly lack the necessary set of refinements of my type in the method signature, but I can understand what is happening here. Any idea?

+8
scala shapeless
source share
1 answer

The last option with everything that is calculated implicitly works for me,

 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 

(result types rejected for readability).

+4
source share

All Articles