on 3d8ef6c help sign in
125 lines 3.3 kB history raw
1-- | The 'State' as an effect with dynamic dispatch.
2--
3-- It's not clear in which situation it's beneficial to use this instead of
4-- "Effective.State" or "Effective.State.MVar" as you either:
5--
6-- - Share state between threads and need the synchonized version.
7--
8-- - Don't share state between threads and are free to use the faster, pure
9-- version.
10--
11-- However, let's include this for now.
12--
13module Effectful.State.Dynamic
14 ( State
16 -- * Pure
17 , runState
18 , evalState
19 , execState
21 -- * MVar
22 , runStateMVar
23 , evalStateMVar
24 , execStateMVar
26 -- * Operations
27 , get
28 , put
29 , state
30 , modify
31 , stateM
32 , modifyM
33 ) where
35import Control.Concurrent.MVar
37import Effectful.Internal.Has
38import Effectful.Internal.Monad
40-- | Provide access to a mutable state of type @s@.
41--
42-- Whether the state is represented as a pure value or an 'MVar' depends on the
43-- interpretation.
44data State s = forall ref. State
45 { _ref :: ref
46 , _get :: forall es. ref -> Eff es s
47 , _put :: forall es. ref -> s -> Eff es ref
48 , _state :: forall es a. ref -> (s -> Eff es (a, s)) -> Eff es (a, ref)
49 }
51----------------------------------------
52-- Pure
54runState :: s -> Eff (State s : es) a -> Eff es (a, s)
55runState s m = evalEffect (statePure s) $ (,) <$> m <*> get
57evalState :: s -> Eff (State s : es) a -> Eff es a
58evalState s = evalEffect (statePure s)
60execState :: s -> Eff (State s : es) a -> Eff es s
61execState s m = evalEffect (statePure s) $ m *> get
63statePure :: s -> State s
64statePure s0 = State
65 { _ref = s0
66 , _get = pure
67 , _put = \_ -> pure
68 , _state = \s f -> f s
69 }
71----------------------------------------
72-- MVar
74runStateMVar :: s -> Eff (State s : es) a -> Eff es (a, s)
75runStateMVar s m = do
76 v <- impureEff_ $ newMVar s
77 evalEffect (stateMVar v) $ (,) <$> m <*> get
79evalStateMVar :: s -> Eff (State s : es) a -> Eff es a
80evalStateMVar s m = do
81 v <- impureEff_ $ newMVar s
82 evalEffect (stateMVar v) m
84execStateMVar :: s -> Eff (State s : es) a -> Eff es s
85execStateMVar s m = do
86 v <- impureEff_ $ newMVar s
87 evalEffect (stateMVar v) $ m *> get
89stateMVar :: MVar s -> State s
90stateMVar v0 = State
91 { _ref = v0
92 , _get = impureEff_ . readMVar
93 , _put = \v s -> impureEff_ . modifyMVar v $ \_ ->
94 s `seq` pure (s, v)
95 , _state = \v f -> impureEff $ \es -> modifyMVar v $ \s0 -> do
96 (a, s) <- unEff (f s0) es
97 s `seq` pure (s, (a, v))
98 }
100----------------------------------------
101-- Operations
103get :: State s :> es => Eff es s
104get = readerEffectM $ \State{..} -> _get _ref
106put :: State s :> es => s -> Eff es ()
107put s = stateEffectM $ \State{..} -> do
108 ref <- _put _ref s
109 pure ((), State { _ref = ref, .. })
111state :: State s :> es => (s -> (a, s)) -> Eff es a
112state f = stateEffectM $ \State{..} -> do
113 (a, ref) <- _state _ref $ pure . f
114 pure (a, State { _ref = ref, .. })
116modify :: State s :> es => (s -> s) -> Eff es ()
117modify f = state (\s -> ((), f s))
119stateM :: State s :> es => (s -> Eff es (a, s)) -> Eff es a
120stateM f = stateEffectM $ \State{..} -> do
121 (a, ref) <- _state _ref f
122 pure (a, State { _ref = ref, .. })
124modifyM :: State s :> es => (s -> Eff es s) -> Eff es ()
125modifyM f = stateM (\s -> ((), ) <$> f s)