-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/

-- | State variables
--   
--   This package contains state variables, which are references in the IO
--   monad, like IORefs or parts of the OpenGL state.
@package StateVar
@version 1.1.0.2

-- | State variables are references in the IO monad, like IORefs or
--   parts of the OpenGL state. Note that state variables are not
--   neccessarily writable or readable, they may come in read-only or
--   write-only flavours, too. As a very simple example for a state
--   variable, consider an explicitly allocated memory buffer. This buffer
--   could easily be converted into a StateVar:
--   
--   
--   makeStateVarFromPtr :: Storable a => Ptr a -> StateVar a
--   makeStateVarFromPtr p = makeStateVar (peek p) (poke p)
--   
--   
--   The example below puts 11 into a state variable (i.e. into the
--   buffer), increments the contents of the state variable by 22, and
--   finally prints the resulting content:
--   
--   
--   do p <- malloc :: IO (Ptr Int)
--      let v = makeStateVarFromPtr p
--      v $= 11
--      v $~ (+ 22)
--      x <- get v
--      print x
--   
--   
--   However, Ptr can be used directly through the same API:
--   
--   
--   do p <- malloc :: IO (Ptr Int)
--      p $= 11
--      p $~ (+ 22)
--      x <- get p
--      print x
--   
--   
--   IORefs are state variables, too, so an example with them looks
--   extremely similiar:
--   
--   
--   do v <- newIORef (0 :: Int)
--      v $= 11
--      v $~ (+ 22)
--      x <- get v
--      print x
--   
module Data.StateVar

-- | This is the class of all readable state variables.
class HasGetter t a | t -> a
get :: (HasGetter t a, MonadIO m) => t -> m a

-- | A concrete implementation of a read-only state variable is simply an
--   IO action to read the value.
type GettableStateVar = IO

-- | Construct a GettableStateVar from an IO action.
makeGettableStateVar :: IO a -> GettableStateVar a

-- | This is the class of all writable state variables.
class HasSetter t a | t -> a

-- | Write a new value into a state variable.
($=) :: (HasSetter t a, MonadIO m) => t -> a -> m ()

-- | This is a variant of $= which is strict in the value to be set.
($=!) :: (HasSetter t a, MonadIO m) => t -> a -> m ()

-- | A concrete implementation of a write-only state variable, carrying an
--   IO action to write the new value.
newtype SettableStateVar a
SettableStateVar :: (a -> IO ()) -> SettableStateVar a

-- | Construct a SettableStateVar from an IO action for writing.
makeSettableStateVar :: (a -> IO ()) -> SettableStateVar a

-- | This is the class of all updatable state variables.
class HasSetter t a => HasUpdate t a b | t -> a b where ($~) = defaultUpdate ($~!) = defaultUpdateStrict

-- | Transform the contents of a state variable with a given funtion.
($~) :: (HasUpdate t a b, MonadIO m) => t -> (a -> b) -> m ()

-- | This is a variant of $~ which is strict in the transformed
--   value.
($~!) :: (HasUpdate t a b, MonadIO m) => t -> (a -> b) -> m ()

-- | A concrete implementation of a readable and writable state variable,
--   carrying one IO action to read the value and another IO action to
--   write the new value. This data type represents a piece of mutable,
--   imperative state with possible side-effects. These tend to encapsulate
--   all sorts tricky behavior in external libraries, and may well throw
--   exceptions. Inhabitants should satsify the following
--   properties:
--   
--   
--   
- In the absence of concurrent mutation from other threads or a
--   thrown exception:
--   
--   
--   
--   do x <- get v; v $= y; v $= x
--   
--   
--   should restore the previous state.
--   
--   
--   
- Ideally, in the absence of thrown exceptions:
--   
--   
--   
--   v $= a >> get v
--   
--   
--   should return a, regardless of a. In practice some
--   StateVars only permit a very limited range of value
--   assignments, and do not report failure.
data StateVar a
StateVar :: (IO a) -> (a -> IO ()) -> StateVar a

-- | Construct a StateVar from two IO actions, one for reading and
--   one for
makeStateVar :: IO a -> (a -> IO ()) -> StateVar a

-- | Change the type of a StateVar
mapStateVar :: (b -> a) -> (a -> b) -> StateVar a -> StateVar b
instance Data.StateVar.HasSetter (Data.StateVar.SettableStateVar a) a
instance Data.StateVar.HasSetter (Data.StateVar.StateVar a) a
instance Foreign.Storable.Storable a => Data.StateVar.HasSetter (GHC.Ptr.Ptr a) a
instance Data.StateVar.HasSetter (GHC.IORef.IORef a) a
instance Data.StateVar.HasSetter (GHC.Conc.Sync.TVar a) a
instance Data.StateVar.HasUpdate (Data.StateVar.StateVar a) a a
instance Foreign.Storable.Storable a => Data.StateVar.HasUpdate (GHC.Ptr.Ptr a) a a
instance Data.StateVar.HasUpdate (GHC.IORef.IORef a) a a
instance Data.StateVar.HasUpdate (GHC.Conc.Sync.TVar a) a a
instance Data.StateVar.HasGetter (Data.StateVar.StateVar a) a
instance Data.StateVar.HasGetter (GHC.Conc.Sync.TVar a) a
instance Data.StateVar.HasGetter (GHC.Types.IO a) a
instance Data.StateVar.HasGetter (GHC.Conc.Sync.STM a) a
instance Foreign.Storable.Storable a => Data.StateVar.HasGetter (GHC.Ptr.Ptr a) a
instance Data.StateVar.HasGetter (GHC.IORef.IORef a) a
