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