I have looked at the cool solution presented by Travis Brown which allows converting case classes between each other in a generic way. I tried to use it to convert HList to a case class but did not managed to get it worked. Here is my attempt:
import shapeless._, ops.hlist.Align
import syntax.std.tuple._
object Shplss extends App {
class SameFieldsConverter[T] {
def apply[S, SR <: HList, TR <: HList](s: S)(implicit
genS: LabelledGeneric.Aux[S, SR],
genT: LabelledGeneric.Aux[T, TR],
align: Align[SR, TR]
) = genT.from(align(genS.to(s)))
}
def convertTo[T] = new SameFieldsConverter[T]
type SomeType = Int :: Int :: String :: Boolean :: Int :: Int :: HNil
final case class SomeProductType(f1: Int, f2: Int, f3: String, f4: Boolean, f5: Int, f6: Int)
val some: SomeType = (4, 4, "ssdf", true, 2, 4).productElements
convertTo[SomeProductType](some)
}
Unfortunately it fails with the error:
Error:(22, 29) could not find implicit value for parameter genS: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeType,SR]
convertTo[SomeProductType](some)
Error:(22, 29) not enough arguments for method apply: (implicit genS: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeType,SR], implicit genT: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeProductType,TR], implicit align: shapeless.ops.hlist.Align[SR,TR])com.test.Shplss.SomeProductType in class SameFieldsConverter.
Unspecified value parameters genS, genT, align.
convertTo[SomeProductType](some)
Is there a way to enhance the converTo[B] function so it can convert between HLists as well?
Shapeless's
GenericandLabelledGenericare type classes that provide a generic representation for case classes and sealed trait hierarchies using hlists and coproducts. If you already have an hlist, you don't really need aGenericinstance, and Shapeless doesn't provide one. In your case this means you can actually skip thegenSandSRparts:This will give you
SomeProductType(4,4,ssdf,true,2,4), as you'd expect.Note that I've changed
genTfromLabelledGenerictoGeneric, since we no longer have labels to align on the input side. I guess you could add some extra machinery to "inject" the unlabeled input into a Shapeless record to match theLabelledGenerictype, but in this specific use case at least there's not really any point.