HList 到嵌套 Map

HList to nested Map

我想将 HList 类型参数转换为嵌套的 Map 类型,例如Int :: String :: String :: HNil 应该变成 Map[Int, Map[String, Map[String, T]]]] ,其中 T 是同一函数的另一个类型参数,例如:

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

其中 f.Out 在 HNil 或具有部门 L.size

的嵌套映射结构的情况下是 T

有什么办法可以做到吗?

我不知道执行此类转换的标准做法,但您可以采用与在 [=13] 内实现各种 HList 操作(如 map)相同的方式推出自定义转换器=].代码可能是这样的:

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)
}

可以看到online