Katakanlah saya memiliki catatan ADT berikut:
data Foo = Bar { a :: Integer, b :: String, c :: String }
Saya ingin fungsi yang mengambil record dan mengembalikan record (dengan tipe yang sama) di mana semua kecuali satu bidang memiliki nilai yang identik dengan yang diteruskan sebagai argumen, seperti:
walkDuck x = Bar { a = a x, b = b x, c = lemonadeStand (a x) (b x) }
Cara di atas berfungsi, tetapi untuk rekaman dengan lebih banyak bidang (katakanlah 10
), membuat fungsi seperti itu akan memerlukan banyak pengetikan yang menurut saya tidak terlalu diperlukan.
Apakah ada cara yang tidak terlalu membosankan untuk melakukan hal yang sama?
Jawaban:
Ya, ada cara yang bagus untuk memperbarui bidang rekaman. Di GHCi Anda dapat melakukan -
sumber
RecordWildCards
ekstensi bisa bagus juga, untuk “membongkar” bidang dalam lingkup. Untuk pembaruan, itu tidak terlalu bagus:incrementA x@Foo{..} = x { a = succ a }
updateFoo x = x.{ c = "Goodbye" }
(perhatikan.
operatornya).Ini adalah pekerjaan yang bagus untuk lensa :
Kemudian:
akan memperbarui bidang 'c' dari 'test' ke string Anda.
sumber
test $ c .~ "Goodbye"
adalah bagaimanalens
melakukannya iirc. Saya tidak mengatakan ini intutitif, tetapi begitu Anda mengetahui operatornya maka saya berharap itu akan datang semudah$
.Anda tidak perlu menentukan fungsi tambahan atau menggunakan lensa. Standar Haskell sudah memiliki apa yang Anda butuhkan. Mari kita ambil contoh oleh Don Stewart:
Kemudian Anda bisa mengatakan
test { c = "Goodbye" }
untuk mendapatkan catatan yang diperbarui.sumber