2016-07-15 33 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'中不存在的任何字段。你會同意嗎? –