doron
doron

Reputation: 28932

Changing only 1 element of a compound data type

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

Answers (2)

danidiaz
danidiaz

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

Jon Purdy
Jon Purdy

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

Related Questions