我正在尝试这个并且它有效:
`
case class Foo(name: String)
class Morphic(map: Map[String, Any]) {
def add(k: String, v: Any) = {
new Morphic((map + (k -> v)))
}
def to[T](): T = {
def toClass[A]: ToCase[A] = new ToCase[A] // This is class to convert from Map to case class
val res = toClass[Foo].from(map).get // <-- problem is here - cannot use T
res.asInstanceOf[T]
}
}
object testApp extends App {
var m = new Morphic(Map[String, Any]())
var m1 = m.add("name", "john")
println(m1.to[Foo])
}
我应该在val res = toClass[T].from(map).get
中使用T而不是Foo,但它没有编译说隐含缺失
toClass[T].from
是一个从Map
如何使隐含的(以及可能依赖于.from的其他人)可用?
我尝试了def to[T, H <: HList]()(implicit gen: LabelledGeneric.Aux[A, H]) = ...
但是我在调用.to时需要指定这两种类型,而我无法弄清楚要为H指定的内容
由于
答案 0 :(得分:1)
您可以将Map
转换为HList
,然后将HList
转换为T
:
import shapeless.{::, HList, HNil, LabelledGeneric, Witness}
import shapeless.labelled._
case class Foo(name: String)
trait MapToHList[L <: HList] {
def apply(map: Map[String, Any]): Option[L]
}
object MapToHList {
implicit object hNilMapToHList extends MapToHList[HNil] {
override def apply(map: Map[String, Any]): Option[HNil] = Some(HNil)
}
implicit def hConsMapToHList[K <: Symbol, V, T <: HList](implicit
mapToHList: MapToHList[T],
witness: Witness.Aux[K]
): MapToHList[FieldType[K, V] :: T] =
new MapToHList[FieldType[K, V] :: T] {
override def apply(map: Map[String, Any]): Option[FieldType[K, V] :: T] = {
val str = witness.value.toString.tail
for {
v <- map.get(str)
t <- mapToHList(map)
} yield field[K](v.asInstanceOf[V]) :: t
}
}
}
trait ToCase[A] {
def from(map: Map[String, Any]): Option[A]
}
object ToCase {
implicit def mkToCase[A, L <: HList](implicit
gen: LabelledGeneric.Aux[A, L],
mapToHList: MapToHList[L]
): ToCase[A] =
new ToCase[A] {
override def from(map: Map[String, Any]): Option[A] = mapToHList(map).map(gen.from)
}
}
class Morphic(map: Map[String, Any]) {
def add(k: String, v: Any) = {
new Morphic((map + (k -> v)))
}
def to[T](implicit toCase: ToCase[T]): T = toCase.from(map).get
}
object testApp extends App {
var m = new Morphic(Map[String, Any]())
var m1 = m.add("name", "john")
println(m1.to[Foo]) // Foo(john)
}
我试过了
指定什么def to[T, H <: HList]()(implicit gen: LabelledGeneric.Aux[A, H]) ...
但是在调用.to时我需要指定这两种类型 我无法弄清楚要为H
您可以将其称为m1.to[Foo, FieldType[Witness.`'name`.T, String] :: HNil]()
或m1.to[Foo, Record.`'name -> String`.T]()
。