136

次のレコードADTがあるとします。

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

次のように、レコードを取得して(同じタイプの)レコードを返す関数が必要です。この場合、フィールドの1つを除くすべてが、引数として渡された値と同じ値になります。

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

上記は機能しますが、より多くのフィールド(たとえば10)を持つレコードの場合、そのような関数を作成すると、多くの入力が必要になり、私はまったく不要だと感じます。

同じことをするための面倒な方法はありますか?

4

3 に答える 3

181

はい、レコード フィールドを更新する良い方法があります。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" }
于 2013-02-19T10:54:42.023 に答える
40

これはレンズにとって良い仕事です:

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

test = Foo 1 2 "Hello"

それで:

setL c "Goodbye" test

「test」のフィールド「c」を文字列に更新します。

于 2013-02-19T14:57:59.710 に答える
25

補助関数を定義したり、レンズを使用したりする必要はありません。標準の Haskell には、必要なものがすでに用意されています。Don Stewart の例を見てみましょう。

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

test = Foo 1 2 "Hello"

test { c = "Goodbye" }次に、更新されたレコードを取得するように言うことができます。

于 2018-08-17T15:33:22.150 に答える