podobne do this case class question ale z niespodzianką:Scalanie dwóch klas przypadków w Scala, ale z głęboko zagnieżdżonych typów, bez obiektywu boilerplate
Mam klasy przypadek, który ma pewne głęboko zagnieżdżonych klas sprawę jako właściwości. Jako prosty przykład
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])
Chciałbym połączyć dwie klasy przypadków foobar razem, przyjmując wartości, które istnieją dla wejścia i stosując je do istniejącej instancji, tworząc uaktualnioną wersję:
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)))
Wiem, że mogę użyć soczewki, aby skomponować głęboko zagnieżdżone aktualizacje nieruchomości; jednak czuję, że będzie to wymagało wiele kodu płyty kotła: potrzebuję soczewki dla każdej własności i innego złożonego obiektywu w klasie rodzica. Wydaje się, że to dużo do utrzymania, nawet jeśli używa się bardziej zwięzłego podejścia do tworzenia soczewek w shapeless.
Najtrudniejszą częścią jest element optionFoo: w tym scenariuszu oba elementy istnieją z Some (value). Jednak chciałbym scalić właściwości opcji wewnętrznej, a nie tylko nadpisać fb1 nowymi wartościami fb2.
Zastanawiam się, czy istnieje dobre podejście do łączenia tych dwóch wartości w sposób, który wymaga minimalnego kodu. Moje odczucia mówią, żebym spróbował użyć metody unapply
w klasie sprawy, aby zwrócić krotkę, powtórzyć i połączyć krotki w nową krotkę, a następnie zastosować krotkę z powrotem do klasy sprawy.
Czy jest to skuteczniejszy sposób na zrobienie tego?
Travis, dzięki za to rozwiązanie. To bardzo interesujące podejście. Jedno pytanie jednak: w jaki sposób możemy rekurencyjnie połączyć dwie wartości (_), które mogą mieć właściwości podrzędności opcji? Na przykład, jeśli właściwość foo w FooBar była foo: Option [Foo], i chciałem zastosować | + | zarówno dla fooPropA, jak i fooPropB? – mhamrah
To jest dokładnie zachowanie domyślnej instancji monoid dla 'Option', która jest tutaj nadpisywana przez drugą instancję (która jest tym, czego szukasz w polach' Option [String] 'i' Option [Int] '). Możesz mieszać i dopasowywać zachowania za pomocą [tagów] (https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/Tags.scala) - Mogę napisać Szybki przykład później, jeśli jesteś zainteresowany. –
Dzięki Travis, naprawdę doceniam próbkę. Jestem nowy w Scalaz i Shapeless - myślę, że wiem, co chcę, ale nie wiem, jak to zrealizować. Tak jak to widzę, kiedy kod dostaje się do elementu w Hlist, który może przekonwertować na Hlist, przekonwertuj go i zastosuj | + | do wewnętrznej hlist i przekształcić z powrotem w klasę przypadków. Zaktualizuję też moje pytanie w tym scenariuszu. – mhamrah