在函数体

时间:2017-10-06 07:05:32

标签: scala shapeless

我正在尝试这个并且它有效:

`
    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指定的内容

由于

1 个答案:

答案 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]()