簡體   English   中英

有沒有辦法以通用方式將 Hlist 轉換為適當的案例 class ?

[英]Is there a way to convert Hlist to an appropriate case class in a generic way?

我看過 Travis Brown 提出的很酷的解決方案,它允許以通用方式在彼此之間轉換案例類。 我嘗試使用它將HList轉換為case 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 converTo[B] function 以便它也可以在HList之間轉換?

Shapeless 的GenericLabelledGeneric是類型類,它們使用 hlists 和 coproducts 為案例類和密封特征層次結構提供通用表示。 如果您已經有一個 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)

請注意,我已將genTLabelledGeneric更改為Generic ,因為我們不再需要在輸入端對齊標簽。 我想您可以添加一些額外的機制來將未標記的輸入“注入”到無形記錄中以匹配LabelledGeneric類型,但在這個特定的用例中至少沒有任何意義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM