【问题标题】:Shapeless - programatically remove fields from case class using LabelledGenericShapeless - 使用 LabelledGeneric 以编程方式从案例类中删除字段
【发布时间】:2019-03-12 09:58:45
【问题描述】:

我在使用 LabelledGeneric 转换为案例类时遇到问题

我的代码的简化示例如下:

import shapeless._
import shapeless.record._

  def removeKeys[
    F <: Product,
    T <: Product,
    HF <: HList,
    HT <: Product
  ](
    from: F,
    removeField: String
  )(
    implicit genericFrom: LabelledGeneric.Aux[F, HF],
    genericTo: LabelledGeneric.Aux[T, HT]
  ): T = {
    val hListFrom = genericFrom.to(from) 
    val hListTo = hListFrom - Witness(removeField) // Missing implicit Remover 
    genericTo.from(hListTo) // If I remove multiple fields in a say foldLeft how do I ensure the resulting HList is of type HT?
  }

我显然错过了一个卸妆器 - 考虑到我最终想要折叠一组标签以删除 hListFrom,我应该如何变出一个?

我的最终目的是从 case class F 中选择 case class T 上存在的具有相同类型的所有字段。

例如,给定:

case class A(a: Int, b: Double, c: Boolean)
case class B(b: Double, c: Boolean)

我想要

def f[F <: Product, T <: Product](cc: F): T

这样f(A(1, 1.0, true)) 返回B(1.0, true)

我想我需要两个 HList 的交集,但是我刚刚想到我需要根据输出案例类构造函数参数的顺序重新排序。

我很喜欢学习 Shapeless,但学习曲线相当陡峭,而且许多示例倾向于省略有关如何确保将隐式传递给通用代​​码的细节。

【问题讨论】:

  • 这里有几个问题(单次删除与折叠多次删除)。我认为如果您专注于第一个问题并提出第二个问题作为后续问题,这将是一个更好的问题。预期用途也不清楚:看起来调用者必须明确指定所有类型参数,因为HT 通常不会唯一标识T。这可能不是您想要的,并且有一些方法可以解决它,但是如果您提供一些示例输入、输出和用法,它会更加清晰。
  • 感谢您的回复。我的最终意图是选择案例类 F 上也存在于案例类 T 上的具有相同类型的所有字段名称,并返回案例类 T 的实例。我将编辑问题以反映这一点。
  • 感谢更新!但是,仍然存在应该如何确定输出类型的问题。一般而言,可能有许多案例类具有A 的成员子集,在这种情况下,f(A(1, 1.0, true)) 将是模棱两可的。
  • 输出类型将被指定为类型参数,忽略函数看起来像def convert[FromType, ToType](instance: FromType): ToType

标签: scala shapeless


【解决方案1】:

关于你的第一部分问题,

  import shapeless._
  import shapeless.ops.record.Remover
  import shapeless.record._

  def removeKeys[
  F <: Product,
  T <: Product,
  HF <: HList,
  HT <: HList,
  V
  ](
     from: F,
     removeField: Witness
   )(
     implicit genericFrom: LabelledGeneric.Aux[F, HF],
     remover: Remover.Aux[HF, removeField.T, (V, HT)],
     genericTo: LabelledGeneric.Aux[T, HT],
  ): T = {
    val hListFrom = genericFrom.to(from)
    val hListTo = hListFrom - removeField
    genericTo.from(hListTo)
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    • 2017-11-24
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    相关资源
    最近更新 更多