我有数据类型:
data Person = Person {
person_id :: Int,
person_firstname :: String,
person_surname :: String,
person_address :: Address
}
我想更改让我们说person_firstname
的值,其中haskell意味着复制其他所有内容。有没有比这更简单的方法:
person'' = Person (person_id person') newName (person_surname person') (person_address person')
答案 0 :(得分:3)
记录更新:
person' = person { person_firstname = newName }
请注意,它适用于任何表达式:
somebody = (Person 0 "Nobody" "Nothingson" "123 Fake St.")
{ person_firstname = "Somebody"
, person_surname = "Somethingson"
}
RecordWildCards
扩展程序还可以为您节省一些打字费用,但我建议您仅将其用于名称离不开您的简短定义:
incrementId person@Person{..} = person { person_id = person_id + 1 }
答案 1 :(得分:2)
另一种方法是使用lens包中的镜片:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Person = Person {
_person_id :: Int,
_person_firstname :: String,
_person_surname :: String,
_person_address :: String
}
makeLenses ''Person
examplePerson = Person 7 "aaa" "bbb" "ccc"
modifiedPerson = set person_firstname "zzz" examplePerson
main :: IO ()
main = do
putStrLn $ view person_firstname modifiedPerson
镜片的优点是它们易于组合;当你有嵌套的数据结构时,它们会派上用场。