Tương tự như this case class question nhưng với một twist:Hợp nhất hai lớp trường hợp tại Scala, nhưng với các loại sâu lồng nhau, mà không cần ống kính soạn sẵn
Tôi có một lớp trường hợp trong đó có một số lớp học trường hợp lồng nhau như tài sản. Như một ví dụ đơn giản,
case class Foo(fooPropA:Option[String], fooPropB:Option[Int])
case class Bar(barPropA:String, barPropB:Int)
case class FooBar(name:Option[String], foo:Foo, optionFoo: Option[Foo], bar:Option[Bar])
tôi muốn hợp nhất hai lớp trường hợp Foobar với nhau, lấy giá trị mà tồn tại cho một đầu vào và áp dụng chúng vào một thể hiện, sản xuất một phiên bản cập nhật:
val fb1 = FooBar(Some("one"), Foo(Some("propA"), None), Some(Foo(Some("propA"), Some(3))), Some(Bar("propA", 4)))
val fb2 = FooBar(None, Foo(Some("updated"), Some(2)), Some(Foo(Some("baz"), None)), None)
val merged = fb1.merge(fb2)
//merged = FooBar(Some("one"), Foo(Some("updated"), Some(2)), Some(Foo(Some("baz"), Some(3))), Some(Bar("propA", 4)))
Tôi biết tôi có thể sử dụng ống kính để soạn bản cập nhật thuộc tính lồng nhau sâu sắc; tuy nhiên, tôi cảm thấy điều này sẽ đòi hỏi rất nhiều mã tấm nồi hơi: Tôi cần một ống kính cho mọi tài sản và một ống kính khác được tạo thành trong lớp cha. Điều này có vẻ như rất nhiều để duy trì, ngay cả khi sử dụng cách tiếp cận sáng tạo ống kính ngắn gọn hơn trong shapeless.
Phần khó khăn là phần tử optionFoo: trong trường hợp này, cả hai phần tử tồn tại với một số (giá trị). Tuy nhiên, tôi muốn hợp nhất các thuộc tính tùy chọn bên trong, không chỉ ghi đè lên fb1 với các giá trị mới của fb2.
Tôi tự hỏi liệu có cách tiếp cận tốt để hợp nhất hai giá trị này lại với nhau theo cách đòi hỏi mã tối thiểu. Cảm giác ruột của tôi bảo tôi cố gắng sử dụng phương thức unapply
trên lớp vỏ để trả về một tuple, lặp lại và kết hợp các bộ dữ liệu vào một bộ tuple mới, và sau đó áp dụng tuple trở lại một lớp chữ.
Có cách nào hiệu quả hơn để thực hiện việc này không?
Travis, cảm ơn vì giải pháp này. Đó là một cách tiếp cận rất thú vị. Tuy nhiên, một câu hỏi: làm cách nào chúng ta có thể kết hợp lại hai giá trị Một số (_) có thể có các thuộc tính phụ Tùy chọn? Ví dụ, nếu thuộc tính foo trong FooBar là foo: Option [Foo], và tôi muốn áp dụng | + | cho cả fooPropA và fooPropB? – mhamrah
Đó chính xác là hành vi của thể hiện monoid mặc định cho 'Option', được ghi đè lên ở đây bởi thể hiện thứ hai (đó là những gì bạn muốn cho các trường' Option [String] 'và' Option [Int] '). Bạn có thể trộn và kết hợp các hành vi bằng cách sử dụng [thẻ] (https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/Tags.scala) —Tôi có thể viết lên ví dụ nhanh sau nếu bạn quan tâm. –
Cảm ơn Travis, tôi thực sự đánh giá cao một mẫu. Tôi là người mới đối với Scalaz và Shapeless - Tôi nghĩ rằng tôi biết những gì tôi muốn xảy ra, nhưng không chắc chắn làm thế nào để thực hiện. Cách tôi thấy nó là khi mã được gửi đến một phần tử trong Hlist mà nó có thể chuyển đổi thành Hlist, chuyển đổi nó và áp dụng | + | vào hlist bên trong và chuyển đổi trở lại một lớp trường hợp. Tôi cũng sẽ cập nhật câu hỏi của mình với kịch bản này. – mhamrah