stateref-0.2.1.1: src/Data/StateRef.hs
{-
- ``StateRef.hs''
- (c) 2008 Cook, J. MR SSD, Inc.
-}
-- |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.Classes
, module Data.StateRef.Instances
, module Data.Accessor
) where
import Data.StateRef.Classes
import Data.StateRef.Instances
import Data.Accessor
-- |Create a reference and constrain its type to be the default reference type
-- for the monad in which it is being created. See 'newRef'.
newDefaultRef :: (DefaultStateRef sr m a, NewRef sr m a) => a -> m sr
newDefaultRef = newRef
-- |Read a reference and constrain its type to be the default reference type
-- for the monad in which it is being read. See 'readRef'.
readDefaultRef :: (DefaultStateRef sr m a, ReadRef sr m a) => sr -> m a
readDefaultRef = readRef
-- |Write a reference and constrain its type to be the default reference type
-- for the monad in which it is being written. See 'writeRef'
writeDefaultRef :: (DefaultStateRef sr m a, WriteRef sr m a) => sr -> a -> m ()
writeDefaultRef = writeRef
-- |Modify a reference and constrain its type to be the default reference type
-- for the monad in which it is being modified. See 'modifyRef'.
atomicModifyDefaultRef :: (DefaultStateRef sr m a, ModifyRef sr m a) => sr -> (a -> (a,b)) -> m b
atomicModifyDefaultRef = atomicModifyRef
-- |Modify a reference and constrain its type to be the default reference type
-- for the monad in which it is being modified. See 'modifyRef'.
modifyDefaultRef :: (DefaultStateRef sr m a, ModifyRef sr m a) => sr -> (a -> a) -> m ()
modifyDefaultRef = modifyRef
-- |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 <- readRef 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 :: (DefaultStateRef sr m1 a,
ModifyRef sr m1 a,
NewRef sr m a,
Enum a) =>
a -> m (m1 a)
newCounter n = do
c <- newRef n
return $ do
x <- readDefaultRef c
writeDefaultRef 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 (-)
--
-- note that there's a unification ghc missed here:
-- the fundep sr -> a on NewRef and DefaultStateRef should cause a and a1
-- to be unified, because of the 2 constraints:
-- NewRef sr1 m a
-- DefaultStateRef sr1 m1 a1
-- this isn't a \"bug\" because the type is still valid, but it seems like
-- something ghc \"ought\" to do, since a and a1 are doomed to unification
-- anyway.
mkLapseReader :: (ReadRef sr m a,
ReadRef sr m1 a,
NewRef sr1 m a,
DefaultStateRef sr1 m1 a1,
ReadRef sr1 m1 a1,
WriteRef sr1 m1 a) =>
sr -> (a -> a1 -> b) -> m (m1 b)
mkLapseReader var f = do
startVal <- readRef var
prevRef <- newRef startVal
return $ do
newVal <- readRef var
prevVal <- readDefaultRef prevRef
writeRef prevRef newVal
return (f newVal prevVal)