2016-07-15 58 views
0

我有以下的设置,在这里我想的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中不存在的额外字段进行硬编码。

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

回答

0

您应该可以使用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和密封特性分解到多个文件时。

+0

谢谢,超级有用!最后一个障碍是,我收到以下编译错误:'在调用copyOver时,无法找到参数更新的隐式值:cmd23.UpdateRepr [cmd19.moreData1,R] copyOver(myData,otherData)'。任何想法为什么? –

+0

如果您尝试使用REPL,请尝试一次性使用具有密封特征,案例类别和'UpdateRepr'的'Ctrl + P'。 –

+0

啊,是的,它适用于在粘贴模式下一次性复制全部内容。谢谢! 最后一个问题:如果我正确理解'UpdateRepr','baseData'必须是'moreData'的一个确切的子集才能工作。含义'baseData'不能有'moreData'中不存在的任何字段。你会同意吗? –