次のレコード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
)、そのような関数を作成すると、多くのタイピングが必要になります。
同じことをするのに退屈な方法はありますか?
はい、レコードフィールドを更新する良い方法があります。 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" }
これは lenses の場合に適しています。
data Foo = Foo { a :: Int, b :: Int , c :: String }
test = Foo 1 2 "Hello"
次に:
setL c "Goodbye" test
「test」のフィールド「c」を文字列に更新します。
補助機能を定義したり、レンズを使用したりする必要はありません。標準のHaskellにはすでに必要なものが揃っています。ドン・スチュワートの例を見てみましょう。
data Foo = Foo { a :: Int, b :: Int , c :: String }
test = Foo 1 2 "Hello"
次に、test { c = "Goodbye" }
更新されたレコードを取得します。