stateref-0.3/0000755000000000000000000000000011301277701011356 5ustar0000000000000000stateref-0.3/Setup.lhs0000644000000000000000000000011611301277701013164 0ustar0000000000000000#!/usr/bin/env runhaskell > import Distribution.Simple > main = defaultMain stateref-0.3/stateref.cabal0000644000000000000000000000632611301277701014166 0ustar0000000000000000name: stateref version: 0.3 stability: provisional license: PublicDomain cabal-version: >= 1.2 build-type: Simple author: James Cook maintainer: James Cook homepage: http://code.haskell.org/~mokus/stateref/ category: Data synopsis: Abstraction for things that work like IORef. description: A collection of type-classes generalizing the read\/write\/modify operations for stateful variables provided by things like IORef, TVar, &c. Note that The interface has changed a bit from the 0.2.* version. \"*Ref\" functions are now called \"*Reference\" and new \"*Ref\" function exist with simpler signatures. The new 'Ref' existential type provides a convenient monad-indexed reference type, and the HasRef class indicates monads for which there is a default reference type for every referent. tested-with: GHC Flag useSTM Description: Include instances for STM types Default: True Flag useTMVar Description: Include instances for TMVar (TMVar is not available in hugs' STM implementation). I have been unable to make this flag's value depend on whether or not you're running hugs, so if you are, you'll just have to change it manually. It'd sure be nice if there were either an explicit backtrack command in cabal or if 'buildable:false' would trigger a backtrack. Or if I could say "default: not(impl(hugs))" for this flag. Note that this is irrelevant at the moment because I broke Hugs+STM support by adding MonadIO m => ... instances. If anyone really wants me to fix it, speak up - but those instances are pretty darn convenient. Default: True Library hs-source-dirs: src extensions: CPP exposed-modules: Data.Accessor Data.StateRef Data.StateRef.Types Data.StateRef.Instances Data.MRef Data.MRef.Types Data.MRef.Instances other-modules: Data.StateRef.Instances.Undecidable if flag(useSTM) other-modules: Data.StateRef.Instances.STM Data.MRef.Instances.STM cpp-options: -DuseSTM if flag(useTMVar) cpp-options: -DuseTMVar if impl(hugs) buildable: False build-depends: base >= 3 && <5, mtl if flag(useSTM) build-depends: stm stateref-0.3/src/0000755000000000000000000000000011301277701012145 5ustar0000000000000000stateref-0.3/src/Data/0000755000000000000000000000000011301277701013016 5ustar0000000000000000stateref-0.3/src/Data/Accessor.hs0000644000000000000000000000120011301277701015105 0ustar0000000000000000{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} module Data.Accessor where import Data.StateRef.Types newtype Getter m a = Getter (m a) newtype Setter m a = Setter (a -> m ()) newtype Accessor m a = Accessor (Getter m a, Setter m a) instance Monad m => ReadRef (Getter m a) m a where readReference (Getter x) = x instance Monad m => WriteRef (Setter m a) m a where writeReference (Setter f) = f instance Monad m => ReadRef (Accessor m a) m a where readReference (Accessor (Getter x, _)) = x instance Monad m => WriteRef (Accessor m a) m a where writeReference (Accessor (_, Setter f)) = f stateref-0.3/src/Data/MRef.hs0000644000000000000000000000046211301277701014205 0ustar0000000000000000module Data.MRef ( module Data.MRef , module Data.MRef.Types , module Data.MRef.Instances ) where import Data.MRef.Types import Data.MRef.Instances -- |See 'takeMRef'. takeMRef :: MRef m a -> m a takeMRef = takeMRef -- |See 'putMRef'. putMRef :: MRef m a -> a -> m () putMRef = putMRef stateref-0.3/src/Data/StateRef.hs0000644000000000000000000000465111301277701015075 0ustar0000000000000000-- |This module provides classes and instances for mutable state -- references. Various implementation exist in common usage, but -- no way (until now ;-) to define functions using state references -- which don't depend on the specific monad or reference type in use. -- -- These modules use several language extensions, including multi-parameter -- type classes and functional dependencies. module Data.StateRef ( module Data.StateRef , module Data.StateRef.Types , module Data.StateRef.Instances , module Data.Accessor ) where import Data.StateRef.Types import Data.StateRef.Instances import Data.Accessor -- |Read a 'Ref'. See 'readReference'. readRef :: Ref m a -> m a readRef = readReference -- |Write a 'Ref'. See 'writeReference' writeRef :: Ref m a -> a -> m () writeRef = writeReference -- |Modify a 'Ref'. See 'modifyReference'. atomicModifyRef :: Ref m a -> (a -> (a,b)) -> m b atomicModifyRef = atomicModifyReference -- |Modify a 'Ref'. See 'modifyReference'. modifyRef :: Ref m a -> (a -> a) -> m () modifyRef = modifyReference -- |Essentially the same concept as 'Control.Monad.State.gets', -- 'Control.Monad.State.asks', et al. Typically useful to read a field of -- a referenced ADT by passing a record selector as the second argument. readsRef :: (ReadRef sr m a, Monad m) => sr -> (a -> b) -> m b readsRef r f = do x <- readReference r return (f x) -- |Construct a counter - a monadic value which, each time it is -- evaluated, returns the 'succ' of the previous value returned. newCounter :: (HasRef m, Monad m, Enum a) => a -> m (m a) newCounter n = do c <- newRef n return $ do x <- readRef c writeRef c (succ x) return x -- |Create a \"lapse reader\" (suggestions for better terminology are more -- than welcome), a sort of a time-lapse of the variable. The first -- motivating instance for this operation was a clock in a simple simulation -- application. Given a 'TVar' 'Double' called \"clock\", a useful -- value \"dT\" is yielded by the expression: 'mkLapseReader' clock (-) mkLapseReader :: (ReadRef sr m a, HasRef m, Monad m) => sr -> (a -> a -> b) -> m (m b) mkLapseReader var f = do startVal <- readReference var prevRef <- newRef startVal return $ do newVal <- readReference var prevVal <- readRef prevRef writeReference prevRef newVal return (f newVal prevVal) stateref-0.3/src/Data/MRef/0000755000000000000000000000000011301277701013647 5ustar0000000000000000stateref-0.3/src/Data/MRef/Instances.hs0000644000000000000000000000172111301277701016133 0ustar0000000000000000{-# LANGUAGE CPP, MultiParamTypeClasses, FlexibleInstances #-} -- |This module exports no new symbols of its own. It defines -- basic class instances for creating, reading, and writing 'MVar's, and -- re-exports 'MVar'. module Data.MRef.Instances ( MVar , MonadIO(..) #ifdef useSTM , module Data.MRef.Instances.STM #endif ) where #ifdef useSTM import Data.MRef.Instances.STM #endif import Data.MRef.Types import Control.Concurrent.MVar import Control.Monad.Trans -- preferred instances -- MVar in IO monad instance HasMRef IO where newMRef x = fmap MRef (newMVar x) newEmptyMRef = fmap MRef newEmptyMVar instance MonadIO m => NewMRef (MVar a) m a where newMReference = liftIO . newMVar newEmptyMReference = liftIO newEmptyMVar instance MonadIO m => TakeMRef (MVar a) m a where takeMReference = liftIO . takeMVar instance MonadIO m => PutMRef (MVar a) m a where putMReference r = liftIO . putMVar r stateref-0.3/src/Data/MRef/Types.hs0000644000000000000000000000332611301277701015313 0ustar0000000000000000{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, GADTs #-} -- |This module defines the \"MRef\" abstraction, which is a set of -- type-classes for things that behave like 'Control.Concurrent.MVar.MVar's. -- See the documentation there for more info. -- -- This interface may be subject to future expansion. Presently, rather -- than providing something like 'Control.Concurrent.MVar.tryTakeMVar', -- instances for \"'Data.StateRef.Types.ReadRef' sr m ('Maybe' a)\" are -- provided, giving 'Data.StateRef.Types.readReference' the same type -- tryTakeMRef would have if it existed. There is currently nothing like -- 'Control.Concurrent.MVar.tryPutMVar', though. Perhaps there should be. -- Or, perhaps this is the sort of thing the weird (to me) signature of -- 'Data.IORef.atomicModifyIORef' is for, and an argument for a similar -- signature for 'Data.StateRef.Types.modifyStateRef' or the addition of -- a new atomicModifyStateRef function. -- -- I would like to resolve these questions in version 0.3 of this package. module Data.MRef.Types where data MRef m a where MRef :: (TakeMRef sr m a, PutMRef sr m a) => !sr -> MRef m a class HasMRef m where newMRef :: a -> m (MRef m a) newEmptyMRef :: m (MRef m a) class Monad m => NewMRef sr m a | sr -> a where -- |See 'Control.Concurrent.MVar.newMVar' newMReference :: a -> m sr -- |See 'Control.Concurrent.MVar.newEmptyMVar' newEmptyMReference :: m sr class Monad m => TakeMRef sr m a | sr -> a where -- |See 'Control.Concurrent.MVar.takeMVar' takeMReference :: sr -> m a class Monad m => PutMRef sr m a | sr -> a where -- |See 'Control.Concurrent.MVar.putMVar' putMReference :: sr -> a -> m () stateref-0.3/src/Data/MRef/Instances/0000755000000000000000000000000011301277701015576 5ustar0000000000000000stateref-0.3/src/Data/MRef/Instances/STM.hs0000644000000000000000000000620411301277701016577 0ustar0000000000000000{-# LANGUAGE CPP, MultiParamTypeClasses, FlexibleInstances #-} -- |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. module Data.MRef.Instances.STM ( STM #ifdef useTMVar , TMVar #endif , TVar , atomically ) where import Data.MRef.Types import Data.StateRef (readReference, writeReference, newReference) import Data.StateRef.Instances.STM () import Control.Concurrent.STM -- MRef STM in IO monad instance NewMRef (MRef STM a) IO a where #ifdef useTMVar newMReference = fmap MRef . newTMVarIO newEmptyMReference = fmap MRef newEmptyTMVarIO #else newMReference = fmap MRef . newTVarIO . Just newEmptyMReference = fmap MRef (newTVarIO Nothing) #endif instance TakeMRef (MRef STM a) IO a where takeMReference (MRef ref) = atomically (takeMReference ref) instance PutMRef (MRef STM a) IO a where putMReference (MRef ref) = atomically . putMReference ref #ifdef useTMVar --TMVar in STM monad instance HasMRef STM where newMRef x = fmap MRef (newTMVar x) newEmptyMRef = fmap MRef newEmptyTMVar instance NewMRef (TMVar a) STM a where newMReference = newTMVar newEmptyMReference = newEmptyTMVar instance TakeMRef (TMVar a) STM a where takeMReference = takeTMVar instance PutMRef (TMVar a) STM a where putMReference = putTMVar -- TMVar in IO monad instance NewMRef (TMVar a) IO a where newMReference = newTMVarIO newEmptyMReference = newEmptyTMVarIO instance TakeMRef (TMVar a) IO a where takeMReference = atomically . takeMReference instance PutMRef (TMVar a) IO a where putMReference ref = atomically . putMReference ref #endif -- incidental instances, which may occasionally be handy in a pinch -- TVars containing "Maybe" values in STM monad. -- Also use as default if TMVar isn't available. #ifndef useTMVar instance HasMRef STM where newMRef x = fmap MRef (newTVar (Just x)) newEmptyMRef = fmap MRef (newTVar Nothing) #endif instance NewMRef (TVar (Maybe a)) STM a where newMReference = newReference . Just newEmptyMReference = newReference Nothing instance TakeMRef (TVar (Maybe a)) STM a where takeMReference ref = do x <- readReference ref case x of Nothing -> retry Just x -> do writeReference ref Nothing return x instance PutMRef (TVar (Maybe a)) STM a where putMReference ref val = do x <- readReference ref case x of Nothing -> writeReference ref (Just val) Just x -> retry -- TVars containing "Maybe" values in IO monad instance NewMRef (TVar (Maybe a)) IO a where newMReference = newReference . Just newEmptyMReference = newReference Nothing instance TakeMRef (TVar (Maybe a)) IO a where takeMReference = atomically . takeMReference instance PutMRef (TVar (Maybe a)) IO a where putMReference ref = atomically . putMReference ref stateref-0.3/src/Data/StateRef/0000755000000000000000000000000011301277701014533 5ustar0000000000000000stateref-0.3/src/Data/StateRef/Instances.hs0000644000000000000000000001566011301277701017026 0ustar0000000000000000{-# LANGUAGE CPP, MultiParamTypeClasses, FlexibleInstances #-} -- |This module exports no new symbols of its own. It defines several -- basic class instances for creating, reading, and writing standard -- reference types, and re-exports the types for which it defines instances. -- -- TODO: add millions of SPECIALIZE INSTANCE pragmas, for IO monad at -- a minimum. module Data.StateRef.Instances ( IORef , MVar , MonadIO(..) , STRef , ST , RealWorld , ForeignPtr #ifdef useSTM , module Data.StateRef.Instances.STM #endif , module Data.StateRef.Instances.Undecidable ) where #ifdef useSTM import Data.StateRef.Instances.STM #endif import Data.StateRef.Types import Data.StateRef.Instances.Undecidable import Data.IORef import Control.Concurrent.MVar import Control.Monad.Trans import Control.Monad.ST import Data.STRef import qualified Control.Monad.ST.Lazy import qualified Data.STRef.Lazy import Foreign.Storable import Foreign.ForeignPtr -- @Ref m@ in @m@: instance HasRef m => NewRef (Ref m a) m a where newReference = newRef instance ReadRef (Ref m a) m a where readReference (Ref sr) = readReference sr instance WriteRef (Ref m a) m a where writeReference (Ref sr) = writeReference sr instance ModifyRef (Ref m a) m a where atomicModifyReference (Ref sr) = atomicModifyReference sr modifyReference (Ref sr) = modifyReference sr -- m a in semi-arbitrary monad m -- (cannot have instance Monad m => ReadRef (m a) m a, because this activates -- functional dependencies that would overconstrain totally unrelated instances -- because of the possibility of the future addition of, e.g., instance Monad TMVar) instance Monad m => NewRef (IO a) m a where newReference ro = return (return ro) instance MonadIO m => ReadRef (IO a) m a where readReference = liftIO instance Monad m => NewRef (ST s a) m a where newReference ro = return (return ro) instance ReadRef (ST s a) (ST s) a where readReference = id instance MonadIO m => ReadRef (ST RealWorld a) m a where readReference = liftIO . stToIO -- IORef in IO-compatible monads instance HasRef IO where newRef x = do sr <- newIORef x return (Ref sr) instance MonadIO m => NewRef (IORef a) m a where newReference = liftIO . newIORef instance MonadIO m => ReadRef (IORef a) m a where readReference = liftIO . readIORef instance MonadIO m => WriteRef (IORef a) m a where writeReference r = liftIO . writeIORef r instance MonadIO m => ModifyRef (IORef a) m a where atomicModifyReference r = liftIO . atomicModifyIORef r modifyReference r = liftIO . modifyIORef r -- @Ref IO@ in IO-compatible monads -- (maybe...) -- instance MonadIO m => NewRef (Ref IO a) m a where -- newReference (Ref sr) = liftIO (newIORef sr) -- instance MonadIO m => ReadRef (Ref IO a) m a where -- readReference (Ref sr) = liftIO (readIORef sr) -- instance MonadIO m => WriteRef (Ref IO a) m a where -- writeReference (Ref sr) = liftIO . writeIORef sr -- instance MonadIO m => ModifyRef (Ref IO a) m a where -- atomicModifyReference (Ref sr) = liftIO . atomicModifyIORef sr -- modifyReference (Ref sr) = liftIO . modifyIORef sr -- (STRef s) in (ST s) monad instance HasRef (ST s) where newRef x = do sr <- newSTRef x return (Ref sr) instance NewRef (STRef s a) (ST s) a where newReference = newSTRef instance ReadRef (STRef s a) (ST s) a where readReference = readSTRef instance WriteRef (STRef s a) (ST s) a where writeReference = writeSTRef instance ModifyRef (STRef s a) (ST s) a where atomicModifyReference = defaultAtomicModifyReference modifyReference = defaultModifyReference -- (STRef RealWorld) in IO monad (not MonadIO instances, because the m -- would overlap with (ST s) even though there's no instance MonadIO (ST a)) instance NewRef (STRef RealWorld a) IO a where newReference = stToIO . newReference instance ReadRef (STRef RealWorld a) IO a where readReference = stToIO . readReference instance WriteRef (STRef RealWorld a) IO a where writeReference r = stToIO . writeReference r instance ModifyRef (STRef RealWorld a) IO a where modifyReference r = stToIO . modifyReference r atomicModifyReference r = stToIO . atomicModifyReference r -- (STRef s) in lazy (ST s) monad instance HasRef (Control.Monad.ST.Lazy.ST s) where newRef x = do sr <- Data.STRef.Lazy.newSTRef x return (Ref sr) instance NewRef (STRef s a) (Control.Monad.ST.Lazy.ST s) a where newReference = Data.STRef.Lazy.newSTRef instance ReadRef (STRef s a) (Control.Monad.ST.Lazy.ST s) a where readReference = Data.STRef.Lazy.readSTRef instance WriteRef (STRef s a) (Control.Monad.ST.Lazy.ST s) a where writeReference = Data.STRef.Lazy.writeSTRef instance ModifyRef (STRef s a) (Control.Monad.ST.Lazy.ST s) a where atomicModifyReference = defaultAtomicModifyReference modifyReference = defaultModifyReference -- MVar in IO-compatible monads (constructable but not usable as a "normal" state ref) instance MonadIO m => NewRef (MVar a) m (Maybe a) where newReference Nothing = liftIO newEmptyMVar newReference (Just x) = liftIO (newMVar x) -- ForeignPtrs, Ptrs, etc., in IO-compatible monads instance (Storable a, MonadIO m) => NewRef (ForeignPtr a) m a where newReference val = liftIO $ do ptr <- mallocForeignPtr withForeignPtr ptr (\ptr -> poke ptr val) return ptr instance (Storable a, MonadIO m) => ReadRef (ForeignPtr a) m a where readReference ptr = liftIO (withForeignPtr ptr peek) instance (Storable a, MonadIO m) => WriteRef (ForeignPtr a) m a where writeReference ptr val = liftIO (withForeignPtr ptr (\ptr -> poke ptr val)) instance (Storable a, MonadIO m) => ModifyRef (ForeignPtr a) m a where atomicModifyReference = defaultAtomicModifyReference modifyReference = defaultModifyReference -- this is an instance I would like to make, but it opens -- a big can of worms... it requires incoherent instances, for one. -- perhaps I ought to give up the abstractness of 'sr' in the class -- definition; i don't know if that gets me anywhere though... -- -- note that as long as only these instances exist, there is no -- actual overlap. maybe it's not such a bad idea. on the other -- hand, a corresponding instance for Reader would be nice too, and -- that would be a duplicate instance (because only the context would -- differ). -- -- instance (MonadState s1 m, -- StateRef s2 m a) -- => StateRef (s1 -> s2) m a -- where -- readReference f = do -- s1 <- get -- readReference (f s1) -- writeReference f val = do -- s1 <- get -- writeReference (f s1) val -- modifyReference f g = do -- s1 <- get -- modifyReference (f s1) g stateref-0.3/src/Data/StateRef/Types.hs0000644000000000000000000000426611301277701016203 0ustar0000000000000000{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, GADTs #-} module Data.StateRef.Types where -- |A simple reference type, hiding the complexity of all these type classes, -- since most of the time the only thing you care about is that you want a reference. -- The full complexity is still there, though, so FFI types or other reference-like -- things can still be made into 'Ref's. data Ref m a where Ref :: ModifyRef sr m a => !sr -> Ref m a class WriteRef sr m a | sr -> a where -- |Replace the existing value of the given reference with the provided value. writeReference :: sr -> a -> m () class ReadRef sr m a | sr -> a where -- |Get the current value referenced by the given state reference. readReference :: sr -> m a class (ReadRef sr m a, WriteRef sr m a) => ModifyRef sr m a | sr -> a where -- |Atomically modify the contents of a reference. This is -- implemented in a separate class (rather than a function with -- context (ReadRef sr m a, WriteRef sr m a)) because in most -- cases the default implementation cannot act atomically. atomicModifyReference :: sr -> (a -> (a,b)) -> m b -- |Same thing, but don't thread out the extra return. Could perhaps -- be implemented slightly more efficiently than 'atomicModifyReference' in many cases. -- Note that implementations are expected to be atomic, if at all possible, -- but not strictly required to be. modifyReference :: sr -> (a -> a) -> m () -- |Default implementation of atomicModifyReference in terms of readReference and writeReference defaultAtomicModifyReference ref f = do x <- readReference ref let (x', b) = f x writeReference ref x' return b -- |Default implementation of modifyReference in terms of readReference and writeReference defaultModifyReference ref f = do x <- readReference ref let x' = f x writeReference ref x' return () class NewRef sr m a | sr -> a where -- |Construct a new reference to the provided value. newReference :: a -> m sr class HasRef m where -- |Construct a new mutable reference (of an unspecified implementation type) containing the provided value. newRef :: a -> m (Ref m a) stateref-0.3/src/Data/StateRef/Instances/0000755000000000000000000000000011301277701016462 5ustar0000000000000000stateref-0.3/src/Data/StateRef/Instances/STM.hs0000644000000000000000000000664411301277701017473 0ustar0000000000000000{-# 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 stateref-0.3/src/Data/StateRef/Instances/Undecidable.hs0000644000000000000000000000146211301277701021220 0ustar0000000000000000{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-} module Data.StateRef.Instances.Undecidable where import Data.StateRef.Types -- |Wrap a state reference that supports reading and writing, and add a -- potentially thread-unsafe 'ModifyRef' instance. newtype UnsafeModifyRef sr = UnsafeModifyRef sr instance ReadRef sr m a => ReadRef (UnsafeModifyRef sr) m a where readReference (UnsafeModifyRef sr) = readReference sr instance WriteRef sr m a => WriteRef (UnsafeModifyRef sr) m a where writeReference (UnsafeModifyRef sr) = writeReference sr instance (Monad m, ReadRef sr m a, WriteRef sr m a) => ModifyRef (UnsafeModifyRef sr) m a where atomicModifyReference = defaultAtomicModifyReference modifyReference = defaultModifyReference