Reputation: 13
I have a quite simple function that is able to instantiate the class of type 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
I'd like to introduce second function:
def parseAll[T <: HList]: T = ???
And use it as follows:
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
Any ideas how can I implement such function?
Upvotes: 1
Views: 152
Reputation: 51703
You can define 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
Actually you can do this without reflection:
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
Upvotes: 0