Ich versuche, Code zu schreiben, der Änderungen in einem Datensatz verfolgt und sie zu einem späteren Zeitpunkt anwendet. In einer dynamischen Sprache würde ich dies tun, indem ich einfach ein Protokoll von List [(String, Any)] -Paaren führe und diese dann einfach als Aktualisierung auf den ursprünglichen Datensatz anwende, wenn ich mich schließlich dazu entschließe, die Änderungen zu übernehmen.Typsichere generische Fallklassenaktualisierung in Scala
Ich muss in der Lage sein, über die Updates zu inspizieren, so dass eine Liste der Update-Funktionen nicht geeignet ist.
In Scala ist dies mit Reflektion ziemlich trivial, aber ich möchte eine typsichere Version implementieren.
Mein erster Versuch war es mit formlos zu versuchen. Das funktioniert gut, wenn wir bestimmte Typen kennen.
import shapeless._
import record._
import syntax.singleton._
case class Person(name:String, age:Int)
val bob = Person("Bob", 31)
val gen = LabelledGeneric[Person]
val updated = gen.from(gen.to(bob) + ('age ->> 32))
// Result: Person("Bob", 32)
Jedoch kann ich nicht herausfinden, wie man diese Arbeit generisch macht.
trait Record[T]
def update(???):T
}
Angesichts der Art und Weise formlos behandelt dies, ich bin mir nicht sicher, ob das überhaupt möglich wäre?
Wenn ich eine Menge Boilerplate akzeptiere, könnte ich als armer mans Version etwas tun, was den folgenden Punkten entspricht.
object Contact {
sealed trait Field[T]
case object Name extends Field[String]
case object Age extends Field[Int]
}
// A typeclass would be cleaner, but too verbose for this simple example.
case class Contact(...) extends Record[Contact, Contact.Field] {
def update[T](field:Contact.Field[T], value:T) = field match {
case Contact.Name => contact.copy(name = value)
case Contact.Age => contact.copy(age = value)
}
}
Dies ist jedoch nicht besonders elegant und erfordert eine Menge Standard. Ich könnte wahrscheinlich mein eigenes Makro schreiben, um damit umzugehen, aber es scheint eine ziemlich gewöhnliche Sache zu sein - gibt es eine Möglichkeit, dies bereits mit Shapeless oder einer ähnlichen Makrobibliothek zu handhaben?
Haben Sie sich die Optik (Linsen, Prismen usw.) angesehen? – rightfold
Wenn ich Objektive richtig verstehe, erlauben sie mir, den Datensatz explizit zu aktualisieren, aber keine Metadaten über Änderungen, die ich später anwenden möchte, zu protokollieren. –
Ich denke, formlos bietet die meisten Teile, die Sie brauchen. Sie können die typsicheren Delta- und Case-Class-A-la-Carte-Beispiele im neuesten formlosen 2.1.0-Snapshot betrachten. Darüber hinaus ist deine Frage nicht präzise genug, dass ich sie beantworten könnte, ohne dir die ganze Sache zu schreiben ;-) –