HList to nested Map

半世苍凉 提交于 2019-12-08 07:52:49

问题


I would like to transform an HList type parameter to a nested Map-type, e.g. 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?


回答1:


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



来源:https://stackoverflow.com/questions/51352776/hlist-to-nested-map

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!