有没有一种方法可以将Hlist以通用的方式转换为合适的case类?

问题描述 投票:3回答:1

我看了一下很酷的 解决办法 由Travis Brown提出的,它允许在通用方式下转换不同的case类。我试着用它来转换 HListcase class 但没有设法让它工作。这是我的尝试。

import shapeless._, ops.hlist.Align
import syntax.std.tuple._

object Shplss  extends App {
  class SameFieldsConverter[T] {
    def apply[S, SR <: HList, TR <: HList](s: S)(implicit
                                                 genS: LabelledGeneric.Aux[S, SR],
                                                 genT: LabelledGeneric.Aux[T, TR],
                                                 align: Align[SR, TR]
    ) = genT.from(align(genS.to(s)))
  }

  def convertTo[T] = new SameFieldsConverter[T]

  type SomeType = Int :: Int :: String :: Boolean :: Int :: Int :: HNil
  final case class SomeProductType(f1: Int, f2: Int, f3: String, f4: Boolean, f5: Int, f6: Int)

  val some: SomeType = (4, 4, "ssdf", true, 2, 4).productElements

  convertTo[SomeProductType](some)
}

不幸的是,它失败的错误。

Error:(22, 29) could not find implicit value for parameter genS: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeType,SR]
  convertTo[SomeProductType](some)


Error:(22, 29) not enough arguments for method apply: (implicit genS: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeType,SR], implicit genT: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeProductType,TR], implicit align: shapeless.ops.hlist.Align[SR,TR])com.test.Shplss.SomeProductType in class SameFieldsConverter.
Unspecified value parameters genS, genT, align.
  convertTo[SomeProductType](some)

有什么办法可以增强 converTo[B] 函数,所以它可以在 HList的也是?

scala functional-programming shapeless hlist
1个回答
5
投票

Shapeless的 GenericLabelledGeneric 是类型类,它使用hlist和coproducts为case类和密封的性状层次提供了一个通用表示。如果你已经有一个hlist,你并不真正需要一个 Generic 例,而Shapeless没有提供。在你的情况下,这意味着你实际上可以跳过 genSSR 部件。

import shapeless._, ops.hlist.Align
import syntax.std.tuple._

object Shplss  extends App {
  class SameFieldsConverter[T] {
    def apply[S <: HList, TR <: HList](s: S)(implicit
      genT: Generic.Aux[T, TR],
      align: Align[S, TR]
    ) = genT.from(align(s))
  }

  def convertTo[T] = new SameFieldsConverter[T]

  type SomeType = Int :: Int :: String :: Boolean :: Int :: Int :: HNil
  final case class SomeProductType(f1: Int, f2: Int, f3: String, f4: Boolean, f5: Int, f6: Int)

  val some: SomeType = (4, 4, "ssdf", true, 2, 4).productElements

  convertTo[SomeProductType](some)
}

这将给你 SomeProductType(4,4,ssdf,true,2,4),正如你所期望的那样。

请注意,我已经改变了 genTLabelledGenericGeneric因为我们不再有标签来对齐输入端。我想你可以添加一些额外的机制来 "注入 "无标签的输入到Shapeless记录中以匹配 LabelledGeneric 类型,但在这个特定的用例中,至少没有任何意义。

© www.soinside.com 2019 - 2024. All rights reserved.