I'm not aware of a standard thing to do such a transformation, but you could roll out your custom converter in the same way as various HList ops (like map) are implemented inside shapeless (see trait Mapper). The code could be something like this:
import scala.language.higherKinds
import scala.collection.immutable.Map
import shapeless._
sealed trait HListToMap[L <: HList, T] {
type Out
def convert(hlist: L, value: T): Out
}
object HListToMap {
// public interface
def wrap[L <: HList, T](value: T, keys: L)(implicit converter: HListToMap[L, T]): converter.Out =
converter.convert(keys, value)
// implementation details
type Aux[L <: HList, T, Out2] = HListToMap[L, T] { type Out = Out2 }
private trait Impl[L <: HList, T, Out2] extends HListToMap[L, T] {
override type Out = Out2
}
implicit def hnil[T]: Aux[HNil, T, T] = new Impl[HNil, T, T] {
override def convert(hlist: HNil, value: T): T = value
}
implicit def hnil2[T]: Aux[HNil.type, T, T] = new Impl[HNil.type, T, T] {
override def convert(hlist: HNil.type, value: T): T = value
}
implicit def recurse[H, L <: HList, T](implicit inner: HListToMap[L, T]): Aux[H :: L, T, Map[H, inner.Out]] = new Impl[H :: L, T, Map[H, inner.Out]] {
override def convert(hlist: H :: L, value: T): Map[H, inner.Out] = {
val im = inner.convert(hlist.tail, value)
Map(hlist.head -> im)
}
}
}
def test(): Unit = {
val keys = "abc" :: 1 :: 0.5 :: HNil
val value = "Xyz"
val m: Map[String, Map[Int, Map[Double, String]]] = HListToMap.wrap(value, keys)
println(m)
val just: String = HListToMap.wrap(value, HNil)
println(just)
}
You can see it online