
Am Samstag, den 11.09.2010, 11:21 -0600 schrieb Jonathan Geddes:
I know that record updates is a topic that has become a bit of a dead horse, but here I go anyway:
I find that most of the record updates I read and write take the form
someUpdate :: MyRecord -> MyRecord someUpdate myRecord = myRecord { field1 = f $ field1 myRecord , field2 = g $ field2 myRecord , field3 = h $ filed3 myRecord }
I find myself wishing I could write something more like
someUpdate :: MyRecord -> MyRecord someUpdate myRecord = myRecord { field1 => f , field2 => g , field3 => h }
with equivalent semantics. Here => reads "is transformed by". Operator = could still be used for assignment as in current record updates.
The best part about such an extension, in my opinion, is that it would open the door for anonymous lambda record updates. Something like:
someUpdate :: MyRecord -> MyRecord someUpdate = \{field1 => f, field2 => g, field3 => h}
again, with the same semantics. This becomes possible because you no longer need to refer to the record within the {} part of the update.
This would be useful, for example, in the State monad. We could write:
someStateTransform :: State MyRecord () someStateTransform = do modify $ \{field1 => (++"!")} ...
where currently we see code like
someStateTransform :: State MyRecord () someStateTransform = do modify $ \record->record{field1 = (++"!") $ field1 record} ...
which repeats the record name 3 times and the field name twice. The repetition just feels out of place next to all the other terse, readable Haskell code in the program.
So what do my fellow haskellers think? Is this idea worth writing up a proposal for?
Alternatively, can you offer me some advice on writing code in Haskell 2010 that avoids the ugly, repetitive style of record update?
--Jonathan
You might want to have a look at the records package: http://hackage.haskell.org/package/records Here is a code example:
import Data.Kind import Data.TypeFun import Data.Record import Data.Record.Combinators
data Surname = Surname deriving (Show) data Age = Age deriving (Show) data Room = Room deriving (Show)
instance Name Surname where name = Surname instance Name Age where name = Age instance Name Room where name = Room
oldData = X :& Surname := "Jeltsch" :& Age := 31 :& Room := "EH/202" `withStyle` Id KindStar
newData = modify (X :& Age := (+2) :& Room := const "HG/2.39") oldData
Evaluating newData gives you:
X :& Surname := "Jeltsch" :& Age := 33 :& Room := "HG/2.39"
If you have any question regarding the records package, please ask, since I’m its author. :-) Best wishes, Wolfgang