ähnlich this case class question aber mit einem Twist:Zusammenführen von zwei Fallklassen in Scala, aber mit tief verschachtelten Typen, ohne Objektiv vorformulierten
ich einen Fall Klasse habe, die einige tief verschachtelte Fall-Klassen als Eigenschaften aufweist. Als einfaches Beispiel,
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])
Ich mag zwei Klassen FooBar Fall zusammen fusionieren, um die Werte nehmen, die für eine Eingabe existieren und sie zu einer vorhandenen Instanz anwenden, um eine aktualisierte Version produziert:
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)))
Ich weiß, dass ich ein Objektiv verwenden kann, um die tief verschachtelten Eigenschaftsaktualisierungen zu verfassen; Ich denke jedoch, dass dies eine Menge Kesselblech-Code erfordern wird: Ich brauche eine Linse für jede Eigenschaft und eine andere zusammengesetzte Linse in der Elternklasse. Dies scheint eine Menge zu halten, selbst wenn man den Ansatz der engeren Linsenerzeugung in shapeless verwendet.
Der schwierige Teil ist das ElementFoo Element: in diesem Szenario existieren beide Elemente mit einem Some (Wert). Allerdings möchte ich die inneren Option Eigenschaften zusammenführen, nicht nur fb1 mit fb2 neue Werte überschreiben.
Ich frage mich, ob es einen guten Ansatz gibt, diese beiden Werte auf eine Weise zusammenzuführen, die minimalen Code erfordert. Mein Bauchgefühl sagt mir, dass ich versuchen soll, die unapply
-Methode für die Fallklasse zu verwenden, um ein Tupel zurückzugeben, zu iterieren und die Tupel zu einem neuen Tupel zu kombinieren und das Tupel dann auf eine Fallklasse anzuwenden.
Gibt es einen effizienteren Weg, dies zu tun?
Travis, danke für diese Lösung. Es ist ein sehr interessanter Ansatz. Eine Frage: Wie können wir zwei Some (_) -Werte kombinieren, die Option Sub-Eigenschaften haben können? Zum Beispiel, was wäre, wenn die foo -Eigenschaft in FooBar foo wäre: Option [Foo], und ich wollte | + | anwenden zu beiden fooPropA und fooPropB? – mhamrah
Das ist genau das Verhalten der Standard-Monoid-Instanz für "Option", das hier von der zweiten Instanz überschrieben wird (was Sie für die Felder "Option [String]" und "Option [Int]" wünschen). Sie können die Verhaltensweisen mithilfe von [tags] (https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/Tags.scala) mischen und anpassen - ich könnte eine schreiben schnelles Beispiel später, wenn Sie interessiert sind. –
Danke Travis, ich würde wirklich eine Probe zu schätzen wissen. Ich bin neu bei Scalaz und Shapeless - ich glaube, ich weiß, was ich will, aber nicht sicher, wie ich es umsetzen soll. Die Art, wie ich es sehe ist, dass, wenn der Code zu einem Element in der Hlist kommt, das in eine Hlist konvertiert werden kann, konvertiert man es und wendet das | + | an in die innere Liste und konvertieren zurück in eine Fallklasse. Ich werde meine Frage auch mit diesem Szenario aktualisieren. – mhamrah