【问题标题】:Scala: Copying a generic case class into anotherScala:将通用案例类复制到另一个
【发布时间】:2016-07-15 22:23:49
【问题描述】:

我有以下设置,我想将baseData 的实例复制到moreData 的实例中:

sealed trait baseData {
  def weight: Int
  def priority: Int
} 

sealed trait moreData {
  def weight: Int
  def priority: Int
  def t: String
  def id: String
} 

case class data1(override val weight: Int, override val priority: Int) extends baseData 
case class moreData1 (override val weight:Int, override val priority: Int, override val t: String, override val id: String)extends moreData

所以将myData复制到下面的otherData中:

val myData = data1(1,1) 
val otherData = moreData1 (2,2,"C","abcd") 

将产生:moreData1(1,1,"C","abcd")

为此,我想使用具有以下签名的函数,因为我将拥有多个扩展 baseDatamoreData 的案例类:

def copyOver[A <:baseData, B <:moreData](from: A, to: B) = {} 

我确定您可以使用 Shapeless 执行此操作,但还没有弄清楚如何操作。有一些例子 (here) 关于复制扩展相同特征的案例类,还有一些 (here) 通过泛型表示在不同案例类之间映射值。但我还没有想出如何使用LabelledGeneric 与传递给copyOver 的特征边界参数。我也不想硬编码otherData 中不存在于myData 中的额外字段。

我正在寻找一个完全通用的实现。有什么想法吗?

【问题讨论】:

    标签: scala generics shapeless


    【解决方案1】:

    您应该能够使用来自your first shapeless exampleUpdateRepr 类型类。

    您可以使用UpdateRepr 定义copyOver,如下所示:

    import shapeless._
    
    // baseData, moreData, data1, moreData1
    // UpdateRepr ...
    
    def copyOver[A <: baseData, B <: moreData, R <: HList](
      from: A,
      to: B
    )(implicit 
      lgen: LabelledGeneric.Aux[A, R],
      update: UpdateRepr[B, R]
    ): B = update(to, lgen.to(from))
    

    你可以使用如下:

    val myData = data1(1,1) 
    val otherData = moreData1(2,2,"C","abcd") 
    
    copyOver(myData, otherData)
    // moreData1 = moreData1(1,1,C,abcd)
    

    请注意,您可能会遇到 SI-7046 的问题,因为 UpdateRepr 的密封特征(Coproduct)类型类派生,您可以在 REPL 或拆分 UpdateRepr 和密封特征时注意到这一点在多个文件上。

    【讨论】:

    • 谢谢,超级有帮助!最后一个障碍是我收到以下编译错误:could not find implicit value for parameter update: cmd23.UpdateRepr[cmd19.moreData1,R] copyOver(myData, otherData) 调用 copyOver 时。知道为什么吗?
    • 如果您正在尝试 REPL,请尝试一次性使用 Ctrl + P 与密封特征、案例类和 UpdateRepr
    • 啊,是的,它在粘贴模式下一次性复制所有内容时有效。谢谢!最后一个问题:如果我正确理解UpdateReprbaseData 必须是moreData 的确切子集才能正常工作。意思是baseData 不能有任何不在moreData 中的字段。你同意吗?
    猜你喜欢
    • 2016-04-13
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多