Proposed addition to stm: atomicallyIO and afterCommit

Simon Marlow marlowsd at gmail.com
Wed Feb 24 04:58:40 EST 2010


John Lauchbury has proposed the following addition to 
Control.Concurrent.STM.  John's proposal is below, comments welcome.

Personally I'm in two minds about this. It certainly captures a useful 
idiom, but it fails the "don't name compositions" test, and one of the 
additions is just a renaming of 'return', which makes it hard to justify.

Cheers,
	Simon

-----
I find I often write STM code with the structure:

   do
     ... IO code ...
     v <- atomically $ do
         ... STM code ...
         if .....
             then do
                 ... STM code ...
                 return (Left ...)
             else do
                 ... STM code ...
                 return (Right ...)
     case v of
         Left ...  -> ... IO actions ...
         Right ... -> ... IO actions ...

where I have to communicate the result of choices inside STM code to 
corresponding code in the outer IO monad. This means that two separate 
parts of the code have to be kept in sync. In this simple case it's 
merely irritating. With larger and more complex structures it can be 
quite tricky to keep right.

Now I use the functions 'atomicallyIO' and 'afterCommit', and can 
structure the code as

   do
     ... IO code ...
     v <- atomicallyIO $ do
         ... STM code ...
         if .....
             then do
                 ... STM code ...
                 afterCommit $ ... IO actions ...
             else do
                 ... STM code ...
                 afterCommit $ ... IO actions ...

As you see, it allows the IO code to be placed in the appropriate part 
of the STM code, ready to be executed when that STM branch is committed.

Here's the code to would be added to the STM module:

----------------------------------------------------------------------
-- 'atomicallyIO' and 'afterCommit' are useful syntactic sugar for a
-- simple continuation paradigm. They allow IO code to be placed within
-- the same block of STM code in which control decisions are made
-- (avoiding the need to communicate those decisions with a data type
-- sent to a subsequent matching case).

atomicallyIO :: STM (IO a) -> IO a
atomicallyIO ioSTM = join $ atomically ioSTM

afterCommit :: IO a -> STM (IO a)
afterCommit mIO = return mIO
----------------------------------------------------------------------

Obviously the code is very simple, but I still find it useful to name 
the paradigm, and to have the specific type declarations to catch errors.



More information about the Libraries mailing list