stateref-0.3: src/Data/StateRef/Instances/STM.hs
{-# LANGUAGE
CPP,
MultiParamTypeClasses,
FlexibleInstances,
IncoherentInstances
#-}
-- |This module exports no new symbols of its own. It defines
-- basic class instances for creating, reading, and writing 'TVar's and
-- (if available) 'TMVar's, and re-exports the types for which it defines
-- instances as well as the 'atomically' function, which is indispensible
-- when playing with this stuff in ghci.
--
-- Note that this module declares incoherent instances. The universe should
-- refrain from imploding on itself as long as you don't define
-- \"instance MonadIO STM\". However, hugs doesn't seem to support
-- overlapping instances, so I may have to give up on the dream of MonadIO
-- everywhere, or introduce some major conditional compilation stuff. (or
-- abandon hugs support)
module Data.StateRef.Instances.STM
( STM
, TVar
#ifdef useTMVar
, TMVar
#endif
, atomically
) where
import Data.StateRef.Types
import Control.Monad.Trans
import Control.Concurrent.STM
-- (STM a) in STM and IO-compatible monads
instance ReadRef (STM a) STM a where
readReference = id
instance MonadIO m => ReadRef (STM a) m a where
readReference = liftIO . atomically
-- TVar in STM monad
instance HasRef STM where
newRef x = do
sr <- newTVar x
return (Ref sr)
instance NewRef (TVar a) STM a where
newReference = newTVar
instance ReadRef (TVar a) STM a where
readReference = readTVar
instance WriteRef (TVar a) STM a where
writeReference = writeTVar
instance ModifyRef (TVar a) STM a where
atomicModifyReference = defaultAtomicModifyReference
modifyReference = defaultModifyReference
-- TVar in IO-compatible monads
instance MonadIO m => NewRef (TVar a) m a where
newReference = liftIO . newTVarIO
instance MonadIO m => ReadRef (TVar a) m a where
readReference = liftIO . atomically . readReference
instance MonadIO m => WriteRef (TVar a) m a where
writeReference ref = liftIO . atomically . writeReference ref
instance MonadIO m => ModifyRef (TVar a) m a where
modifyReference ref = liftIO . atomically . modifyReference ref
atomicModifyReference ref = liftIO . atomically . atomicModifyReference ref
-- @Ref STM@ in IO-compatible monads
instance MonadIO m => NewRef (Ref STM a) m a where
newReference x = do
sr <- liftIO (newTVarIO x)
return (Ref sr)
instance MonadIO m => ReadRef (Ref STM a) m a where
readReference (Ref sr) = liftIO (atomically (readReference sr))
instance MonadIO m => WriteRef (Ref STM a) m a where
writeReference (Ref sr) = liftIO . atomically . writeReference sr
instance MonadIO m => ModifyRef (Ref STM a) m a where
modifyReference (Ref sr) = liftIO . atomically . modifyReference sr
atomicModifyReference (Ref sr) = liftIO . atomically . atomicModifyReference sr
#ifdef useTMVar
-- TMVar in STM monad
instance NewRef (TMVar a) STM (Maybe a) where
newReference Nothing = newEmptyTMVar
newReference (Just x) = newTMVar x
instance ReadRef (TMVar a) STM (Maybe a) where
readReference tmv = fmap Just (readTMVar tmv) `orElse` return Nothing
-- TMVar in IO-compatible monad
instance MonadIO m => NewRef (TMVar a) m (Maybe a) where
newReference Nothing = liftIO newEmptyTMVarIO
newReference (Just x) = liftIO (newTMVarIO x)
instance MonadIO m => ReadRef (TMVar a) m (Maybe a) where
readReference = liftIO . atomically . readReference
#endif