Reputation: 28932
I have the data type:
data Person = Person {
person_id :: Int,
person_firstname :: String,
person_surname :: String,
person_address :: Address
}
I would like to change let say the value of person_firstname
which in haskell means copying everything else. Is there an easier way to do this than:
person'' = Person (person_id person') newName (person_surname person') (person_address person')
Upvotes: 1
Views: 148
Reputation: 27766
Another way of doing it is by using lenses from the lens package:
{-# 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
Lenses have the advantage that they are easily composable; they come in handy when you have nested data structures.
Upvotes: 2
Reputation: 55069
Record update:
person' = person { person_firstname = newName }
Note that it works on any expression:
somebody = (Person 0 "Nobody" "Nothingson" "123 Fake St.")
{ person_firstname = "Somebody"
, person_surname = "Somethingson"
}
The RecordWildCards
extension can also save you some typing, but I recommend it only for short definitions where the names can’t get away from you:
incrementId person@Person{..} = person { person_id = person_id + 1 }
Upvotes: 3