简体   繁体   中英

HList to nested Map

I would like to transform an HList type parameter to a nested Map-type, eg Int :: String :: String :: HNil should become Map[Int, Map[String, Map[String, T]]]] where T would be another type parameter of the same function, like:

def somedef[T, L <: HList](t: T)(implicit f: ???): f.Out

where f.Out is T in case of HNil or a nested Map-structure with dept L.size

Is there any way this can be done?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM