Допустим, у меня есть следующая запись 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
) создание такой функции повлечет за собой много набора текста, который, как мне кажется, совершенно не нужен.
Есть ли менее утомительные способы сделать то же самое?
Ответы:
Да, есть хороший способ обновить поля записи. В GHCi вы можете сделать -
источник
RecordWildCards
Расширение может быть хорошо , как хорошо, чтобы «Распаковать» полей в области. Для обновлений это не так хорошо:incrementA x@Foo{..} = x { a = succ a }
updateFoo x = x.{ c = "Goodbye" }
(обратите внимание на.
оператор).Это хорошая работа для линз :
Затем:
обновит поле 'c' из 'test' до вашей строки.
источник
test $ c .~ "Goodbye"
какlens
бы это сделать iirc. Я не говорю, что это интуитивно понятно, но если вы знаете операторы, я думаю, это будет так же легко, как$
.Вам не нужно определять дополнительные функции или использовать линзы. В стандартном Haskell уже есть все, что вам нужно. Возьмем пример Дона Стюарта:
Затем вы можете просто сказать,
test { c = "Goodbye" }
чтобы получить обновленную запись.источник