layers-0.1: Modular type class machinery for monad transformer stacks.

Safe HaskellNone




This module exports:

  1. The MonadMutVar type class and its operations newRef, readRef, writeRef and atomicModifyRef.
  2. Instances of MonadMutVar for IO, STM, strict ST and lazy ST.
  3. A universal pass-through instance of MonadMutVar for any existing MonadMutVar wrapped by a MonadLayer.
  4. The utility operations atomicModifyRef', atomicWriteRef, modifyRef and modifyRef'.


The MonadMutVar class

class Monad m => MonadMutVar ref m | m -> ref whereSource

The type class MonadMutVar represents the class of monads which support mutable variables. The ref parameter is the type of the mutable variable; e.g., for IO, ref is IORef.

Minimal complete definition: newRef, readRef, writeRef.


newRef :: a -> m (ref a)Source

Create a new mutable variable holding the value supplied.

readRef :: ref a -> m aSource

Return the current value stored in the mutable variable.

writeRef :: ref a -> a -> m ()Source

Write the supplied value into the mutable variable

atomicModifyRef :: ref a -> (a -> (a, b)) -> m bSource

Atomically modifies the contents of a mutable variable.

This function is useful for using mutable varibales in a safe way in a multithreaded program. If you only have one mutable variable, then using atomicModifyRef to access and modify it will prevent race conditions.

Extending the atomicity to multiple mutable variables is problematic, so it is recommended that if you need to do anything more complicated then using MVar instead is a good idea.

atomicModifyRef does not apply the function strictly. This is important to know even if all you are doing is replacing the value. For example, this will leak memory:

 ref <- newIORef 1
 forever $ atomicModifyRef ref (\_ -> (2, ()))

Use atomicModifyRef' or atomicWriteRef to avoid this problem.


atomicModifyRef' :: MonadMutVar ref m => ref a -> (a -> (a, b)) -> m bSource

Strict version of atomicModifyRef. This forces both the value stored in the mutable variable as well as the value returned.

atomicWriteRef :: MonadMutVar ref m => ref a -> a -> m ()Source

Variant of writeRef with the "barrier to reordering" property that atomicModifyRef has.

modifyRef :: MonadMutVar ref m => ref a -> (a -> a) -> m ()Source

Mutate the contents of a mutable variable.

Be warned that modifyRef does not apply the function strictly. This means if the program calls modifyRef many times, but seldomly uses the value, thunks will pile up in memory resulting in a space leak. This is a common mistake made when using a mutable varible as a counter. For example, the following will likely produce a stack overflow:

 ref <- newRef 0
 replicateM_ 1000000 $ modifyRef ref (+1)
 readRef ref >>= print

To avoid this problem, use modifyRef' instead.

modifyRef' :: MonadMutVar ref m => ref a -> (a -> a) -> m ()Source

Strict version of modifyRef.