George Russell wrote: > Simon Peyton-Jones wrote: > > > > | In the meantime, I'm glad we have got a new function > > | atomicModifyIORef > > | which I for one will use, when it gets into GHC's regular release. > > > > Just before this gets out of the door... any chance of calling it > > > > modifyIORef > > > > and documenting that it's atomic > > My vote goes for > > modifyIORef :: IORef a -> (a -> (a,b)) -> IO b > modifyIORef_ :: IORef a -> (a -> a) -> IO a > > modifyIORef_ ioRef fn = modifyIORef ioRef (\ a0 -> let a1 = fn a0 in (a1,a1)) > > The names are similar to those of GHC's modifyMVar and modifyMVar_. > I think there's some sense in providing modifyIORef_ as well as > modifyIORef, as I think for some implementations it will be even faster, > since it's unnecessary to create thunks for (fst (fn a0)) and > (snd (fn a0)). But you lot know a lot more about writing Haskell > compilers than I do . . . > > Thus you can implement a counter returning integers 1,2,3,... > via > > newCounter :: IO (IO Integer) > newCounter = do > ioRef <- newIORef 0 > return (modifyIORef_ ioRef (+1)) > > I don't think it's necessary for the name to include "atomic". > We are unlikely ever to want a non-atomic version of atomicModifyIORef, > especially as such a thing would be quite dangerous, and you can roll > your own from readIORef and writeIORef.
I like the idea of consistency (in naming, signatures, and semantics) between the sets of functions manipulating IORefs and MVars. Here's the scheme I would prefer for the "modify" subset of these functions. Existing functions are labeled "(e)", proposed functions "(p)". "(*)" indicates an existing function with a different interface. (e) modifyMVar :: MVar a -> (a -> IO (a, b)) -> IO b (e) modifyMVar_ :: MVar a -> (a -> IO a) -> IO () (p) atomicModifyMVar :: MVar a -> (a -> (a, b)) -> IO b (p) atomicModifyMVar_ :: MVar a -> (a -> a) -> IO () (*) modifyIORef :: IORef a -> (a -> IO (a, b)) -> IO b (p) modifyIORef_ :: IORef a -> (a -> IO a) -> IO () (p) atomicModifyIORef :: IORef a -> (a -> (a, b)) -> IO b (p) atomicModifyIORef_ :: IORef a -> (a -> a) -> IO () Notes: * I prefer having the "*modify*_" functions return IO (), despite the fact that it means the newCounter example George gives becomes more complicated. * I strongly agree with Alastair that an atomic function should be so labeled. * The nonatomic functions are all simply convenient combinations of other functions. As such, they could be dispensed with. Even if they were dispensed with, however, I would recommend against using their (without-"atomic") names for the atomic functions, because I think the natural interfaces for the nonatomic names are the ones given above. * In fact, only atomicModifyMVar and atomicModifyIORef are primitive. * The existence of modifyIORef with the "wrong" interface is an unfortunate problem with this scheme. -- Dean _______________________________________________ FFI mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/ffi