假设您有类似以下的案例类
case class Test1(a:String,b:Int,c:Char)
case class Test2(a:String,b:Int)
Run Code Online (Sandbox Code Playgroud)
并使用以下变量实例化类
val test1 = Test1("first",2,'3')
val test2 = Test2("1st",20)
Run Code Online (Sandbox Code Playgroud)
有没有办法使用该.copy方法(或其他方法),将Test2中的变量应用于Test1,如
val test3 = test1.copy(test2) //Note this isn't valid scala code
// Result should be ("1st",20,'3')
Run Code Online (Sandbox Code Playgroud)
如果在纯scala中这是不可能的,那么它将如何在Shapeless 1/2中完成(当前代码在Shapeless 1中,但我们计划在某个时间点升级到Shapeless 2)
我使用shapeless进行case类转换,我有一个2个案例类:
import shapeless._
case class Foo(id: Int, name: String)
case class Bar(id: Int, name: String, price: Double)
val fooGen = Generic[Foo]
val barGen = Generic[Bar]
val foo = Foo(1, "foo")
val fooRepr = fooGen.to(foo)
val additional = fooRepr :+ 1.0
val bar = barGen.from(additional)
Run Code Online (Sandbox Code Playgroud)
这工作正常,但当我尝试将Bar转换为Foo时
fooGen.from(barGen.to(bar))
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:
found : main.barGen.Repr
[error] (which expands to) shapeless.::[Int,shapeless.:: [String,shapeless.::[Double,shapeless.HNil]]]
[error] required: main.fooGen.Repr
[error] (which expands to) shapeless.::[Int,shapeless.::[String,shapeless.HNil]]
[error] println(fooGen.from(barGen.to(bar)))
Run Code Online (Sandbox Code Playgroud)
是否有可能将一个案例类转换为更多字段而不是另一个案例类?
我看过Travis Brown 提出的很酷的解决方案,它允许以通用方式在彼此之间转换案例类。我试图用它来转换HList为 acase 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, …Run Code Online (Sandbox Code Playgroud) 我知道使用 Shapeless 我可以做这样的事情:
import shapeless._, syntax.singleton._, record._
case class Foo(x: Int, y: String)
case class RichFoo(x: Int, y: String, z: Double)
def makeRich(foo: Foo): RichFoo = {
val x = ('z ->> 0.9)
val repr = LabelledGeneric[Foo].to(foo) + x
LabelledGeneric[RichFoo].from(repr)
}
val a = Foo(1, "hello")
val b = makeRich(a)
Run Code Online (Sandbox Code Playgroud)
现在我想写一个通用的方法来做到这一点:
trait Morph[A, B, AR, BR] {
def apply(a: A)(f: AR => BR): B
}
object Morph {
implicit def genericMorph[A, B, AR, BR](implicit genA: LabelledGeneric.Aux[A, AR], genB: LabelledGeneric.Aux[B, BR]): …Run Code Online (Sandbox Code Playgroud)