I've got the following code to basically iterate through the fields of a case class
and map them using a Poly
to the same type and use ToList[HL, Out]
For simplicity we can assume the Poly
does this:
object Schema extends Poly1 {
implicit def caseInt = at[Int](_ => "I'm an int")
implicit def caseString = at[String](_ => "Oh boy a string")
}
def infer[V1 <: Product, Out <: HList, MapperOut <: HList](v1: V1)(
implicit gen: Generic.Aux[V1, Out],
map: Mapper.Aux[Schema.type, Out, MapperOut],
to: ToList[MapperOut, String]
): List[String] = to (gen to v1 map Schema)
This is all very straightforward and works very well for simple scenarios:
case class Test(id: Int, text: String)
val list = infer(Test(2, "text"))
// List("I'm an int", "Oh boy a string")
Now going out to where the buses don't run:
class Automagical[T <: Product with Serializable : TypeTag] {
def instance: T
// The typetag bit is needed for something else
def convert: List[String] = infer(instance)
}
Sadly any call to above fails with:
could not find implicit value for parameter gen: shapeless.Generic.Aux[T,Out]
Bonus
How can I improve the infer
method by not requiring an instance of T
at all? Obviously type inference is fine, but I do need to somehow materialise a List[String]
from an HList[Lub]
and map over something.
Given I only ever care about the types, is it possible to derive a concrete instance of List[String]
by only knowing the types to be poly mapped encoded as an HList?
Something like:
def infer[V1 <: Product, Out <: HList, MapperOut <: HList]()(
implicit gen: Generic.Aux[V1, Out],
map: Mapper.Aux[Schema.type, Out, MapperOut],
to: ToList[MapperOut, String]
): List[String] = {
// Magically build an HList with samples from its types.
// Or an alternative approach that gives the same outcome
val reifiedInstance = reify[Out]
to (reifiedInstance map Schema)
}
To ensure that convert
has access to the implicit parameters for infer
, they have to be present when the Automagical
instance is created:
abstract class Automagical[T <: Product with Serializable : TypeTag,
Out <: HList, MapperOut <: HList]
(implicit
gen: Generic.Aux[T, Out],
map: Mapper.Aux[Schema.type, Out, MapperOut],
to: ToList[MapperOut, String]) {
def instance: T
// The typetag bit is needed for something else
def convert: List[String] = infer(instance)
}