access to fields in nested records
Serge D. Mechveliani
mechvel at botik.ru
Wed Nov 5 15:27:15 EST 2003
Dear Haskellers,
My question is about a nice way to provide a getting/setting
access to the nested record fields.
Example:
---------------------------------------------------------------
data House = House {houseNo :: Int,
diningRoom :: DiningRoom
} deriving (Show)
data DiningRoom = DRoom {square :: Int,
height :: Int,
numOfWindows :: Int,
diningTable :: DTable
} deriving (Show)
data DTable = DTable {tableSquare :: Int,
diningPlaces :: Int
} deriving (Show)
-- example:
r1 = DRoom {square = 50,
height = 300,
numOfWindows = 1,
diningTable = dt
}
where dt = DTable {tableSquare = 16,
diningPlaces = 12
}
---------------------------------------------------------------
Question 1: how to change a field in a record?
I see the following way. For example,
setSquare :: DiningRoom -> Int -> DiningRoom
setSquare r n =
DRoom {square = n,
height = height r,
numOfWindows = numOfWindows r,
diningTable = diningTable r
}
Example of usage: setSquare r1 (square r2)
for
r1, r2 :: DiningRoom
Has indeed one to program the above functions, like setSquare,
for all the records,
or there exist some Haskell annotations, or standard library
function for such purpose, which allow to skip extra remaining
fields in the data, like these three fields in DiningRoom ?
Question 2: how to get/update a field in a nested record?
For example,
dtableSquareFromRoom :: DiningRoom -> Int
dtableSquareFromHouse :: House -> Int
dtableSquareFromRoom = tableSquare . diningTable
dtableSquareFromHouse = dtableSquareFromRoom . diningRoom
setDTableSquareToHouse :: House -> Int -> House
setDTableSquareToHouse h n =
House {
houseNo = houseNo h,
diningRoom = setDTableSquareToRoom (diningRoom h) n
}
where setDTableSquareToRoom r n = ...
Has indeed one to program such functions for each path to a
field in the record nesting hierarchy?
I see the main difficulty in a great number of functions to use
for the same field access from different structures.
I try to improve this by adding classes with get_ and set_
versions of operations for the record fields:
class HouseLike a where get_houseNo :: a -> Int
get_diningRoom :: a -> DiningRoom
set_houseNo :: a -> Int -> a
set_diningRoom :: a -> DiningRoom -> a
...
Now, defining the instances, say, for get_dtableSquare,
set_dtableSquare,
makes it a unique function pair to use for getting/setting of the
corresponding field starting from
House or DiningRoom or DiningTable.
Is this all a reasonable design for a Haskell user program?
Thank you in advance for the respond.
Please, add mechvel at botik.ru
to the reply list.
------------------
Serge Mechhveliani
mechvel at botik.ru
More information about the Haskell
mailing list