-- |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 :: forall (m :: * -> *) a. Ref m a -> m a
readRef = Ref m a -> m a
forall sr (m :: * -> *) a. ReadRef sr m a => sr -> m a
readReference

-- |Write a 'Ref'.  See 'writeReference'
writeRef :: Ref m a -> a -> m ()
writeRef :: forall (m :: * -> *) a. Ref m a -> a -> m ()
writeRef = Ref m a -> a -> m ()
forall sr (m :: * -> *) a. WriteRef sr m a => sr -> a -> m ()
writeReference

-- |Modify a 'Ref'.  See 'modifyReference'.
atomicModifyRef :: Ref m a -> (a -> (a,b)) -> m b
atomicModifyRef :: forall (m :: * -> *) a b. Ref m a -> (a -> (a, b)) -> m b
atomicModifyRef = Ref m a -> (a -> (a, b)) -> m b
forall sr (m :: * -> *) a b.
ModifyRef sr m a =>
sr -> (a -> (a, b)) -> m b
atomicModifyReference


-- |Modify a 'Ref'.  See 'modifyReference'.
modifyRef :: Ref m a -> (a -> a) -> m ()
modifyRef :: forall (m :: * -> *) a. Ref m a -> (a -> a) -> m ()
modifyRef = Ref m a -> (a -> a) -> m ()
forall sr (m :: * -> *) a.
ModifyRef sr m a =>
sr -> (a -> a) -> m ()
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 :: forall sr (m :: * -> *) a b.
(ReadRef sr m a, Monad m) =>
sr -> (a -> b) -> m b
readsRef sr
r a -> b
f = do
    a
x <- sr -> m a
forall sr (m :: * -> *) a. ReadRef sr m a => sr -> m a
readReference sr
r
    b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> b
f a
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 :: forall (m :: * -> *) a. (HasRef m, Monad m, Enum a) => a -> m (m a)
newCounter a
n = do
    Ref m a
c <- a -> m (Ref m a)
forall (m :: * -> *) a. HasRef m => a -> m (Ref m a)
newRef a
n
    m a -> m (m a)
forall (m :: * -> *) a. Monad m => a -> m a
return (m a -> m (m a)) -> m a -> m (m a)
forall a b. (a -> b) -> a -> b
$ do
        a
x <- Ref m a -> m a
forall (m :: * -> *) a. Ref m a -> m a
readRef Ref m a
c
        Ref m a -> a -> m ()
forall (m :: * -> *) a. Ref m a -> a -> m ()
writeRef Ref m a
c (a -> a
forall a. Enum a => a -> a
succ a
x)
        a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
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 :: forall sr (m :: * -> *) a b.
(ReadRef sr m a, HasRef m, Monad m) =>
sr -> (a -> a -> b) -> m (m b)
mkLapseReader sr
var a -> a -> b
f = do
    a
startVal <- sr -> m a
forall sr (m :: * -> *) a. ReadRef sr m a => sr -> m a
readReference sr
var
    Ref m a
prevRef <- a -> m (Ref m a)
forall (m :: * -> *) a. HasRef m => a -> m (Ref m a)
newRef a
startVal
    
    m b -> m (m b)
forall (m :: * -> *) a. Monad m => a -> m a
return (m b -> m (m b)) -> m b -> m (m b)
forall a b. (a -> b) -> a -> b
$ do
        a
newVal <- sr -> m a
forall sr (m :: * -> *) a. ReadRef sr m a => sr -> m a
readReference sr
var
        a
prevVal <- Ref m a -> m a
forall (m :: * -> *) a. Ref m a -> m a
readRef Ref m a
prevRef
        
        Ref m a -> a -> m ()
forall sr (m :: * -> *) a. WriteRef sr m a => sr -> a -> m ()
writeReference Ref m a
prevRef a
newVal
        
        b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> a -> b
f a
newVal a
prevVal)