effectful-0.0.0.0: src/Effectful/State/MVar.hs
-- | The 'State' as an effect.
--
-- Represented as an MVar underneath, therefore:
--
-- - slower than "Effective.State"
--
-- - suitable for sharing between multiple threads.
--
module Effectful.State.MVar
( State
, runState
, evalState
, execState
, get
, put
, state
, modify
, stateM
, modifyM
) where
import Control.Concurrent.MVar
import Effectful.Internal.Has
import Effectful.Internal.Monad
-- | Provide access to a synchronized, mutable state of type @s@.
newtype State s = State (MVar s)
runState :: s -> Eff (State s : es) a -> Eff es (a, s)
runState s m = do
v <- impureEff_ $ newMVar s
evalEffect (State v) $ (,) <$> m <*> get
evalState :: s -> Eff (State s : es) a -> Eff es a
evalState s m = do
v <- impureEff_ $ newMVar s
evalEffect (State v) m
execState :: s -> Eff (State s : es) a -> Eff es s
execState s m = do
v <- impureEff_ $ newMVar s
evalEffect (State v) $ m *> get
get :: State s :> es => Eff es s
get = do
State v <- getEffect
impureEff_ $ readMVar v
put :: State s :> es => s -> Eff es ()
put s = do
State v <- getEffect
impureEff_ . modifyMVar_ v $ \_ -> s `seq` pure s
state :: State s :> es => (s -> (a, s)) -> Eff es a
state f = do
State v <- getEffect
impureEff_ . modifyMVar v $ \s0 -> let (a, s) = f s0 in s `seq` pure (s, a)
modify :: State s :> es => (s -> s) -> Eff es ()
modify f = state (\s -> ((), f s))
stateM :: State s :> es => (s -> Eff es (a, s)) -> Eff es a
stateM f = do
State v <- getEffect
impureEff $ \es -> modifyMVar v $ \s0 -> do
(a, s) <- unEff (f s0) es
s `seq` pure (s, a)
modifyM :: State s :> es => (s -> Eff es s) -> Eff es ()
modifyM f = stateM (\s -> ((), ) <$> f s)