是否可以使用无形来将1个对象转换为另一个对象
进行一些小的转换,例如将Option [T]转换为T. (没有手动定义每个类的映射)
忽略缺少的字段
导入shapeless._ import shapeless.syntax ._
case class Cat(color: Option[Int], isFat: Boolean, newField: String)
case class Kitten(color: Int, isFat: Boolean)
val kitten = Kitten(2, true)
val genCat = Generic[Cat]
val genKit = Generic[Kitten]
val cat: Cat = genCat.from(genKit.to(kitten))
此操作失败,出现以下错误 (扩展为)无形。:: [Int,shapeless。:: [Boolean,shapeless.HNil]]
答案 0 :(得分:0)
以下是使用与previous answer相同的创意解决方案。
当然有一些限制。
object HListsFlatten {
import shapeless.{::, HList, HNil}
sealed trait DefaultValue[V] {
def value: V
}
implicit val defaultInt: DefaultValue[Int] = new DefaultValue[Int] {
override def value = 0
}
sealed trait HConv[From <: HList, To <: HList] {
def convert(list: From): To
}
implicit def buildHConvNil: HConv[HNil, HNil] = new HConv[HNil, HNil] {
override def convert(list: HNil): HNil = HNil
}
implicit def buildHConvShorten[H <: AnyVal, T <: HList]
: HConv[::[H, T], ::[H, HNil]] = new HConv[::[H, T], ::[H, HNil]] {
override def convert(list: ::[H, T]): ::[H, HNil] = {
list.head :: HNil
}
}
implicit def buildHConvOption[H, T <: HList, T2 <: HList](
implicit conv: HConv[T, T2],
default: DefaultValue[H]): HConv[::[Option[H], T], ::[H, T2]] =
new HConv[::[Option[H], T], ::[H, T2]] {
override def convert(list: ::[Option[H], T]): ::[H, T2] = {
list.head.getOrElse(default.value) :: conv.convert(list.tail)
}
}
implicit def buildHConv[H <: AnyVal, T <: HList, T2 <: HList](
implicit conv: HConv[T, T2]): HConv[::[H, T], ::[H, T2]] =
new HConv[::[H, T], ::[H, T2]] {
override def convert(list: ::[H, T]): ::[H, T2] = {
list.head :: conv.convert(list.tail)
}
}
implicit def buildHConvString[T <: HList, T2 <: HList](
implicit conv: HConv[T, T2]): HConv[::[String, T], ::[String, T2]] =
new HConv[::[String, T], ::[String, T2]] {
override def convert(list: ::[String, T]): ::[String, T2] = {
list.head :: conv.convert(list.tail)
}
}
def flatten[A <: HList, B <: HList](list: A)(implicit conv: HConv[A, B]): B =
conv.convert(list)
}
示例:
import shapeless.Generic
case class Cat(color: Option[Int], isFat: Boolean, newField: String)
case class Kitten(color: Int, isFat: Boolean)
val cat = Cat(color = Some(3), isFat = true, "SomeValue")
val genCat = Generic[Cat]
val genKit = Generic[Kitten]
import HListsFlatten._
scala> val kitten = genKit.from(flatten(genCat.to(cat)))
kitten: Kitten = Kitten(3,true)