scala - 将 HList 转换为另一个 HList

标签 scala shapeless

我正在尝试通过转换为 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
}

您希望类型类ConverterT 转换为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/

相关文章:

scala - 如何将元素附加到 HList

python - 在开发 Spark 应用程序时使用多种语言

json - 如何为 Map[Int, Long] 编写 Json 读取组合器

scala - `T {}` 在 Scala 中做什么

scala - 我如何最好地构造具有默认值的无形记录?

scala - 如何创建带有公共(public) getter 的私有(private)字段和采用同名参数的主构造函数的 Scala 类

scala - Spark 集群无法从远程 Scala 应用程序分配资源

scala - 如何使用仿函数创建泛型类型类函数

scala - 是否可以更新实现共同特征的任何案例类的字段

scala - 在 Scala 中的案例类上应用递归操作