module Data.StateVar.Trans (
HasGetter(..),
GettableStateVar, makeGettableStateVar,
HasSetter(..),
SettableStateVar, makeSettableStateVar,
StateVar, makeStateVar, makePtrVar,
($~), ($=!), ($~!),
(&),
(^=), (^~), (^=!), (^~!), (^.),
(@=)
) where
import Data.IORef (IORef, readIORef, writeIORef)
import GHC.Conc (STM, TVar, readTVar, writeTVar)
import Data.STRef (STRef, readSTRef, writeSTRef)
import Foreign.Ptr (Ptr)
import Foreign.Storable
import Control.Monad.ST.Safe (ST)
import Control.Monad.Trans (MonadTrans(..))
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Reader.Class (MonadReader(..))
infixr 2 $=
class HasGetter g m | g -> m where
get :: g a -> m a
instance HasGetter IORef IO where
get = readIORef
instance HasGetter TVar STM where
get = readTVar
instance HasGetter (STRef s) (ST s) where
get = readSTRef
newtype GettableStateVar m a = GettableStateVar (m a)
instance HasGetter (GettableStateVar m) m where
get (GettableStateVar g) = g
makeGettableStateVar :: m a -> GettableStateVar m a
makeGettableStateVar = GettableStateVar
class HasSetter s m where
($=) :: s a -> a -> m ()
instance HasSetter IORef IO where
($=) = writeIORef
instance HasSetter TVar STM where
($=) = writeTVar
instance HasSetter (STRef s) (ST s) where
($=) = writeSTRef
newtype SettableStateVar m a = SettableStateVar (a -> m ())
instance HasSetter (SettableStateVar m) m where
($=) (SettableStateVar s) a = s a
makeSettableStateVar :: (a -> m ()) -> SettableStateVar m a
makeSettableStateVar = SettableStateVar
data StateVar m a =
StateVar (GettableStateVar m a) (SettableStateVar m a)
instance HasGetter (StateVar m) m where
get (StateVar g _) = get g
instance HasSetter (StateVar m) m where
($=) (StateVar _ s) a = s $= a
makeStateVar :: m a -> (a -> m ()) -> StateVar m a
makeStateVar g s = StateVar (makeGettableStateVar g) (makeSettableStateVar s)
makePtrVar :: (MonadIO m, Storable a) => Ptr a -> StateVar m a
makePtrVar p = makeStateVar (liftIO $ peek p) (liftIO . poke p)
($~) :: (Monad m, HasGetter v m, HasSetter v m) => v a -> (a -> a) -> m ()
v $~ f = get v >>= ($=) v . f
($=!) :: (Monad m, HasSetter s m) => s a -> a -> m ()
v $=! x = x `seq` v $= x
($~!) :: (Monad m, HasGetter v m, HasSetter v m) => v a -> (a -> a) -> m ()
v $~! f = get v >>= ($=!) v . f
(&) :: s -> (s -> t) -> t
s & t = t s
infixl 8 ^=, ^~, ^=!, ^~!, ^.
(^=) :: HasSetter g m => (s -> g a) -> a -> s -> m ()
(fv ^= v) s = fv s $= v
(^~) :: (Monad m, HasGetter g m, HasSetter g m) => (s -> g a) -> (a -> a) -> s -> m ()
(fv ^~ f) s = v $~ f where v = fv s
(^=!) :: (Monad m, HasSetter g m) => (s -> g a) -> a -> s -> m ()
(fv ^=! x) s = v $=! x where v = fv s
(^~!) :: (Monad m, HasGetter g m, HasSetter g m) => (s -> g a) -> (a ->a) -> s -> m ()
(fv ^~! f) s = v $~! f where v = fv s
(^.) :: (Monad m, HasGetter g m, HasGetter h m) => (s -> g a) -> (a -> h b) -> s -> GettableStateVar m b
(fg ^. fh) s = makeGettableStateVar $ get (fg s) >>= get . fh
(@=) :: (Monad m, MonadTrans n, MonadReader s (n m), HasSetter g m) => (s -> g a) -> a -> n m ()
fv @= v = ask >>= lift . (fv ^= v)