Сокращенный способ назначения одного поля в записи при копировании остальных полей?

Скажем, у меня есть следующая запись ADT:

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

Мне нужна функция, которая берет запись и возвращает запись (того же типа), где все, кроме одного, поля имеют одинаковые значения для аргумента, переданного как аргумент:

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

Вышеупомянутые работы, но для записи с большим количеством полей (скажем 10), создание такой функции повлечет за собой много типизации, которое, как мне кажется, совершенно не нужно.

Есть ли менее утомительные способы сделать то же самое?

Ответ 1

Да, есть хороший способ обновления полей записей. В GHCi вы можете сделать -

> 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" }

Ответ 2

Это хорошая работа для объективов:

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

test = Foo 1 2 "Hello"

Тогда:

setL c "Goodbye" test

обновит поле 'c' 'test' к вашей строке.