【问题标题】:Using shapeless scala to merge the fields of two different case classes使用 shapeless scala 合并两个不同案例类的字段
【发布时间】:2015-10-19 07:58:26
【问题描述】:

我想将两个不同案例类的字段合并到一个案例类中。

例如,如果我有以下案例类:

case class Test(name:String, questions:List[Question], date:DateTime)

case class Answer(answers:List[Answers])

我想要一种简洁的无形方式将两者合并为:

TestWithAnswers(name:String, questions:List[Question], date:DateTime, answers:List[Answer]). 

那里有一个很好的无形答案吗?

【问题讨论】:

    标签: scala shapeless


    【解决方案1】:

    你可以使用 shapeless Generic 来做到这一点。

    val t: Test = ???
    val a: Answer = ???
    val gt = Generic[Test]
    val ga = Generic[Answer]
    val gta = Generic[TestWithAnswers]
    
    val ta = gta.from(gt.to(t) ++ ga.to(a))
    

    或者好吧,如果你有一个单行的东西

    val ta = Generic[TestWithAnswers].from(Generic[Test].to(t) ++ Generic[Answer].to(a))
    

    如果tTest 的实例,aAnswer 的实例,ta 将是TestWithAnswers 的实例。

    简单说明:Generic 可以将案例类转换为通用 HList 表示。因此,鉴于您的类的结构,您可以简单地将测试和答案都转换为一个 hlist,将两个列表连接成一个列表并从中构建一个 TestWithAnswers 实例。

    这是一个更简单的示例,您可以复制粘贴并在 REPL 中尝试

    import shapeless._
    case class A(a: Int)
    case class B(a: String)
    case class AB(a: Int, b: String)
    Generic[AB].from(Generic[A].to(A(42)) ++ Generic[B].to(B("foo")))
    // AB(42, "foo")
    

    【讨论】:

    • 你的意思是 val ta = gta.from(gt.to(t) ++ at.to(a)) 而不是 val ta = gta.from(gt.to(t) ++ gt.to(a))?即使我进行了更改,代码仍然无法编译。看起来 ++ 运算符不是 gt.to(t) 的成员。有什么想法吗?谢谢
    • 也感谢Generic的解释。很有帮助。
    • @azuras,是的,错字已经修复。都是无形的导入了吗?我在 repl 中运行了代码,它工作了
    • 是的,你当然是对的。 Intellij 显示错误,但 repl 显示它是正确的!谢谢你的帮助。非常好的解决方案
    • 假设如果我们想要这样。 TestWithAnswers(name:String, questions:List[Question], answers:List[Answer]) 。我们该怎么办?
    猜你喜欢
    • 2017-11-24
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2016-09-17
    相关资源
    最近更新 更多