stateref-0.3: src/Data/StateRef/Types.hs
{-# 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)