access to fields in nested records
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@botik.ru to the reply list. ------------------ Serge Mechhveliani mechvel@botik.ru
I think the following notation is all you need: let x = DRoom 5 7 8 (DTable 1 2) y = x { square = 6, diningTable = diningTable x { tableSquare = 1 }} in ... - Hal On Wed, 5 Nov 2003, Serge D. Mechveliani wrote:
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@botik.ru to the reply list.
------------------ Serge Mechhveliani mechvel@botik.ru
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
-- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume
participants (2)
-
Hal Daume III -
Serge D. Mechveliani