我正在尝试通过转换为 HList 将一个案例类转换为另一个案例类。
case class Source(p1:S1, p2:S2) -> HList[S1:+:S2] -> HList[D1:+:D2] ->case class Destination(p1:D1,p2:D2)
我可以通过 gem.to 从 Source 转换为 HList,并通过 gen.from 从 HList 转换为 Destination。
我为 Source 上的每种类型的参数编写了一个 Converter,将其转换为 Destination 中相应的类型,但我不确定如何递归遍历 HList。我的尝试如下所示 hlistEncoder
trait Converter[T] {
def convert(t:T): Datastructure
}
object Converter {
implicit object StrDatastructure extends Converter[String]{
def convert(t:String) = Datastructure.Str(t)
}
implicit object NumDatastructure extends Converter[Double]{
def convert(t :Double) = Datastructure.Num(t)
}
implicit object IncDatastructure extends Converter[Inc]{
def convert(t :Inc) = Datastructure.Incc(t)
}
implicit def SeqDatastructure[T: Converter]: Converter[Seq[T]] = new Converter[Seq[T]]{
def convert(t: Seq[T]) = {
Datastructure.Listt(t.map(implicitly[Converter[T]].convert):_*)
}
}
//HList traversals
implicit object hnilDatastructure extends Converter[HNil]{
def convert(t: HNil) = Datastructure.Hnill(t)
}
implicit def hlistEncoder[H, T <: HList](implicit
hEncoder: Converter[H],
tEncoder: Converter[T]
): Converter[H :: T] = new Converter[H :: T] {
def apply(h:H, t:T)= {
case (h :: t) => hEncoder.convert(h) ++ tEncoder.convert(t)
}
}
}
我使用此方法来测试 HList 到 HList 的转换
def convertToDatastructureN[T](x: T)(implicit converter: Converter[T]): Datastructure = {
converter.convert(x)
}
case class Inc(i:Int)
case class Source(i: Int, n:Inc)
val x = Generic[Source]
val xHlist = x.to(Source(99, Inc(5)))
convertToDatastructureN(xHlist)
有什么想法可以实现hlistEncoder
吗?
最佳答案
我猜你有
sealed trait Datastructure
object Datastructure {
case class Str(t: String) extends Datastructure
case class Num(t: Double) extends Datastructure
case class Incc(t: Inc) extends Datastructure
case class Listt(t: Datastructure*) extends Datastructure
case class Hnill(t: HNil) extends Datastructure
}
您希望类型类Converter
将T
转换为Datastruction
。而且 (HList[S1:+:S2] -> HList[D1:+:D2]
,我猜 ::
应该代替 :+ :
)您希望将 HList
的子类型转换为 HList
的子类型(而不是转换为 HList
本身,因为否则 Generic
无法恢复案例类别)。所以要么你应该修改你的类型类
trait Converter[T] {
type Out
def convert(t:T): Out
}
或者您需要两个类型类:原始的 Converter
和
trait HListConverter[T <: HList] {
type Out <: HList
def convert(t:T): Out
}
此外,目前您的 Converter
还很粗糙。它将每个 T
转换为 Datastruction
,而不是转换为 Datastruction
的特定子类型。这意味着Generic
将能够仅恢复形状的案例类
MyClass(x: Datastructure)
MyClass(x: Datastructure, y: Datastructure)
...
这真的是你想要的吗?如果是这样,那么好吧,如果不是,你需要
MyClass(x: Str)
MyClass(x: Num, y: Incc)
...
那么你又需要
trait Converter[T] {
type Out
def convert(t:T): Out
}
您可以使用标准的shapeless.ops.hlist.Mapper
来代替HListConverter
。
关于scala - 将 HList 转换为另一个 HList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59276266/