it-swarm.dev

Kurzform zum Zuweisen eines einzelnen Feldes in einem Datensatz, während der Rest der Felder kopiert wird?

Angenommen, ich habe den folgenden Datensatz ADT:

data Foo = Bar { a :: Integer, b :: String, c :: String }

Ich möchte eine Funktion, die einen Datensatz aufnimmt und einen Datensatz (desselben Typs) zurückgibt, bei dem alle Felder bis auf eines den gleichen Wert haben wie das als Argument übergebene.

walkDuck x = Bar { a = a x, b = b x, c = lemonadeStand (a x) (b x) }

Das obige funktioniert, aber für einen Datensatz mit mehr Feldern (sagen Sie 10) würde das Erstellen einer solchen Funktion eine Menge Tipparbeit erfordern, die ich für unnötig halte.

Gibt es weniger langweilige Möglichkeiten, dasselbe zu tun?

106
jaymmer

Ja, es gibt eine gute Möglichkeit, Datensatzfelder zu aktualisieren. In GHCi können Sie Folgendes tun:

> data Foo = Foo { a :: Int, b :: Int, c :: String }  -- define a Foo
> let foo = Foo { a = 1, b = 2, c = "Hello" }         -- create a Foo
> let updateFoo x = x { c = "Goodbye" }               -- function to update Foos
> updateFoo foo                                       -- update the Foo
Foo {a = 1, b = 2, c = "Goodbye" }
139
Chris Taylor

Dies ist ein guter Job für Objektive :

data Foo = Foo { a :: Int, b :: Int , c :: String }

test = Foo 1 2 "Hello"

Dann:

setL c "Goodbye" test

würde das Feld 'c' von 'test' auf Ihre Zeichenkette aktualisieren.

31
Don Stewart

Sie müssen keine Zusatzfunktionen definieren oder Objektive verwenden. Standard Haskell hat bereits das, was Sie brauchen. Nehmen wir das Beispiel von Don Stewart:

data Foo = Foo { a :: Int, b :: Int , c :: String }

test = Foo 1 2 "Hello"

Dann kannst du einfach test { c = "Goodbye" }, um einen aktualisierten Datensatz zu erhalten.

10