我有一个非常简单的函数,它能够实例化C类的类:
def parse[C: ClassTag]: C = implicitly[ClassTag[C]].runtimeClass.getCanonicalName match {
case "int" ⇒ 10.asInstanceOf[C]
case "double" ⇒ 10d.asInstanceOf[C]
case "java.lang.String" ⇒ "qwerty".asInstanceOf[C]
}
parse[Int] // res0: Int = 10
parse[Double] // res1: Double = 10.0
parse[String] // res2: qwerty = String
我想介绍第二个功能:
def parseAll[T <: HList]: T = ???
使用如下:
val defaults: Int :: Double :: String :: HNil = parseAll[Int :: Double :: String :: HNil]
// res3: shapeless.::[Int,shapeless.::[Double,shapeless.::[String,shapeless.HNil]]] = 10 :: 10.0 :: qwerty :: HNil
任何想法如何实现这样的功能?
答案 0 :(得分:0)
您可以定义type class ParseAll
:
import shapeless.{::, HList, HNil}
import scala.reflect.ClassTag
def parse[C: ClassTag]: C = implicitly[ClassTag[C]].runtimeClass.getCanonicalName match {
case "int" ⇒ 10.asInstanceOf[C]
case "double" ⇒ 10d.asInstanceOf[C]
case "java.lang.String" ⇒ "qwerty".asInstanceOf[C]
}
def parseAll[T <: HList](implicit p: ParseAll[T]): T = p.apply
trait ParseAll[T <: HList] {
def apply: T
}
object ParseAll {
implicit def hCons[H: ClassTag, T <: HList](implicit p: ParseAll[T]): ParseAll[H :: T] = new ParseAll[H :: T] {
override def apply: H :: T = parse[H] :: p.apply
}
implicit val hNil: ParseAll[HNil] = new ParseAll[HNil] {
override def apply: HNil = HNil
}
}
parseAll[Int :: Double :: String :: HNil] // 10 :: 10.0 :: "qwerty" :: HNil
实际上你可以不加思考地做到这一点:
import shapeless.{::, HList, HNil}
def parse[C](implicit p: Parse[C]): C = p.apply
trait Parse[C] {
def apply: C
}
object Parse {
implicit val int: Parse[Int] = new Parse[Int] {
override def apply: Int = 10
}
implicit val double: Parse[Double] = new Parse[Double] {
override def apply: Double = 10.0
}
implicit val string: Parse[String] = new Parse[String] {
override def apply: String = "qwerty"
}
}
def parseAll[T <: HList](implicit p: ParseAll[T]): T = p.apply
trait ParseAll[T <: HList] {
def apply: T
}
object ParseAll {
implicit def hCons[H, T <: HList](implicit parse: Parse[H], parseAll: ParseAll[T]): ParseAll[H :: T] = new ParseAll[H :: T] {
override def apply: H :: T = parse.apply :: parseAll.apply
}
implicit def hNil: ParseAll[HNil] = new ParseAll[HNil] {
override val apply: HNil = HNil
}
}
parseAll[Int :: Double :: String :: HNil] // 10 :: 10.0 :: "qwerty" :: HNil