简体   繁体   English

将 HList 转换为另一个 HList

[英]transform HList into another HList

I'm trying to convert a case class into another via conversion to HList.我正在尝试通过转换为 HList 将案例类转换为另一个案例类。

case class Source(p1:S1, p2:S2) -> HList[S1:+:S2] -> HList[D1:+:D2] ->case class Destination(p1:D1,p2:D2)

I can convert from Source to HList via gem.to and from HList to Destination via gen.from.我可以通过 gem.to 从 Source 转换为 HList,通过 gen.from 从 HList 转换为 Destination。 I wrote a Converter for each type of parameter on Source to convert it to its corresponding type in Destination but I am unsure how to recursively traverse the HList.我为 Source 上的每种类型的参数编写了一个转换器,以将其转换为 Destination 中的相应类型,但我不确定如何递归遍历 HList。 My attempt is shown below in hlistEncoder我的尝试显示在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)
    }

  }

}

I use this method to test HList to HList conversion我用这个方法来测试 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)

Any ideas how to implement hlistEncoder ?任何想法如何实现hlistEncoder

I guess you have我猜你有

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
}

You want your type class Converter to transform T into Datastructure .您希望您的类型类ConverterT转换为Datastructure But also ( HList[S1:+:S2] -> HList[D1:+:D2] , where I guess :: should be instead of :+: ) you want subtypes of HList to be transformed into subtypes of HList (not into HList itself since otherwise Generic can't restore case class).而且( HList[S1:+:S2] -> HList[D1:+:D2] ,我猜::应该代替:+: )您希望HList子类型转换为HList子类型(而不是HList本身,否则Generic无法恢复 case 类)。 So either you should modify your type class所以要么你应该修改你的类型类

trait Converter[T] {
  type Out
  def convert(t:T): Out
}

or you need two type classes: your original Converter and或者你需要两个类型类:你原来的Converter

trait HListConverter[T <: HList] {
  type Out <: HList
  def convert(t:T): Out
}

Moreover, currently your Converter is pretty rough.此外,目前您的Converter非常粗糙。 It transforms every T into Datastructure instead of into specific subtypes of Datastructure .它把每一个TDatastructure ,而不是插入的特定亚型Datastructure This means Generic will be able to restore case classes only of shapes这意味着Generic将能够仅恢复形状的案例类

MyClass(x: Datastructure) 
MyClass(x: Datastructure, y: Datastructure) 
...

Is it really what you want?真的是你想要的吗? If so then ok, if not and you need如果是,那么可以,如果不是,你需要

MyClass(x: Str) 
MyClass(x: Num, y: Incc) 
...

then again you need然后你又需要

trait Converter[T] {
  type Out
  def convert(t:T): Out
}

Instead of HListConverter you can use standard shapeless.ops.hlist.Mapper .取而代之的HListConverter你可以使用标准shapeless.ops.hlist.Mapper

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM