1

How can I generalize non-trivial record updates? Here is simple example that explicitly updates item references to their new owner.

data Owner = Owner {
        items :: [Item]
          } deriving (Show)

data Item = Item {
        name :: String,
        owner :: Owner
          }   

instance Show Item where
        show (Item name _) = name

item1 = Item "a" owner1
item2 = Item "b" owner1
item3 = Item "c" owner1
owner1 = Owner [item1,item2,item3,Item "d" owner1]

owner2 = Owner $ map (\(Item n o) -> Item n owner2) $ items owner1
Rumca
  • 1,769
  • 8
  • 16
  • You're probably looking for the lens library – DiegoNolan Nov 08 '13 at 21:45
  • 4
    I daresay the best thing would be to forget about `Owner`s. Such references may have their use in object-oriented programming, but since objects in functional programming are just "dumb data" there's generally little point to them knowing about their owner. Sure enough, there _are_ applications where you need some kind of mutual references, but often you can have a library structure take the bookkeeping off you. The most general such structure being a _graph_. – leftaroundabout Nov 08 '13 at 21:48
  • Also, you can remove owners and still navigate a nested (tree-like) data structure using _zippers_. – Robin Green Nov 08 '13 at 22:29
  • You might like [How do you represent a graph in Haskell?](http://stackoverflow.com/q/9732084/791604). – Daniel Wagner Nov 09 '13 at 01:35

1 Answers1

0

Note that in Haskell values are immutable, so you can't change the value of owner1 or item1.

I think the data structure you are looking for is Map OwnerId [Item] - i.e. a map whose keys are some owner id (a String or Int) and whose values are lists of items (the items owned by the owner):

type OwnerId = Int -- or String
data Item = Item { owner :: OwnerId, name :: String }

type WhoOwnsWhat = Map OwnerId [Item]

When you change the owner of an item you are really creating a new map by updating the two map entries with the new list of items. To reassign an item you specify the current map of who owns what, the item and the new owner and get back a new map of who owns what:

changeOwner :: WhoOwnsWhat -> Item -> OwnerId -> WhoOwnsWhat

Adding a new item involves a function like:

addItem :: WhoOwnsWhat -> Item -> WhoOwnsWhat

Note that in each case we are creating a new map.

ErikR
  • 50,049
  • 6
  • 66
  • 121