继续讨论有关转换case classes
和Map[String,Any]
的问题,当我想以通用方式使用它时遇到了一些问题,Here是主要的讨论。
当我想使用像下面这样的通用方法时,编译器会抱怨这些含义:
import MapConvertor._
def convert[A](cc: A)= {
cc.toMapRec
}
以下是提供toMapRec
的完整代码:
import shapeless._, labelled.FieldType, record._
trait ToMapRec[L <: HList] { def apply(l: L): Map[String, Any] }
trait LowPriorityToMapRec {
implicit def hconsToMapRec1[K <: Symbol, V, T <: HList](implicit
wit: Witness.Aux[K],
tmrT: ToMapRec[T]
): ToMapRec[FieldType[K, V] :: T] =
new ToMapRec[FieldType[K, V] :: T] {
def apply(l: FieldType[K, V] :: T): Map[String, Any] =
tmrT(l.tail) + (wit.value.name -> l.head)
}
}
object ToMapRec extends LowPriorityToMapRec {
implicit val hnilToMapRec: ToMapRec[HNil] = new ToMapRec[HNil] {
def apply(l: HNil): Map[String, Any] = Map.empty
}
implicit def hconsToMapRec0[K <: Symbol, V, R <: HList, T <: HList](implicit
wit: Witness.Aux[K],
gen: LabelledGeneric.Aux[V, R],
tmrH: ToMapRec[R],
tmrT: ToMapRec[T]
): ToMapRec[FieldType[K, V] :: T] = new ToMapRec[FieldType[K, V] :: T] {
def apply(l: FieldType[K, V] :: T): Map[String, Any] =
tmrT(l.tail) + (wit.value.name -> tmrH(gen.to(l.head)))
}
}
object MapConvertor {
implicit class ToMapRecOps[A](val a: A) extends AnyVal {
def toMapRec[L <: HList](implicit
gen: LabelledGeneric.Aux[A, L],
tmr: ToMapRec[L]
): Map[String, Any] = tmr(gen.to(a))
}
}
答案 0 :(得分:4)
您需要证明代表source ~/.bash_profile
的记录有A
个实例,您可以这样做:
ToMapRec
您还可以引入一个新的类型来清理它:
def convert[A, R <: HList](cc: A)(implicit
gen: LabelledGeneric.Aux[A, R],
tmr: ToMapRec[R]
) = tmr(gen.to(cc))
然后你的方法只需要一个隐含参数:
trait CcToMapRec[A] { def apply(a: A): Map[String, Any] }
object CcToMapRec {
implicit def ccToMapRec[A, R <: HList](implicit
gen: LabelledGeneric.Aux[A, R],
tmr: ToMapRec[R]
): CcToMapRec[A] = new CcToMapRec[A] {
def apply(a: A): Map[String, Any] = tmr(gen.to(a))
}
}
但是您仍然需要通过任何具有您想要转换的泛型类型的方法来线程化此实例。