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


допустим, у меня есть следующая запись 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), создание такой функции повлечет за собой много ввода, что я чувствую себя совершенно ненужным.

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

3 94

3 ответа:

Да, есть хороший способ обновления полей записи. В 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" }

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

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

test = Foo 1 2 "Hello"

затем:

setL c "Goodbye" test

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

вам не нужно определять вспомогательные функции или использовать линзы. Стандартный Haskell уже имеет то, что вам нужно. Давайте возьмем пример Дона Стюарта:

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

test = Foo 1 2 "Hello"

затем вы можете просто сказать test { c = "Goodbye" } для получения обновленной записи.