module Control.Eff.State(
State
, getState
, putState
, onState
, runState
, Reader
, getReader
, runReader
, local
, Writer
, putWriter
, runWriter
, runPusher
) where
import Control.Applicative ((<$>), (<|>))
import Data.Typeable
import Control.Eff
data State s w = State (s -> s) (s -> w)
deriving (Typeable, Functor)
putState :: Typeable e => Member (State e) r => e -> Eff r ()
putState = onState . const
getState :: Typeable e => Member (State e) r => Eff r e
getState = send (inj . State id)
onState :: (Typeable s, Member (State s) r) => (s -> s) -> Eff r ()
onState f = send (\k -> inj (State f (\_ -> k ())))
runState :: Typeable s
=> s
-> Eff (State s :> r) w
-> Eff r (s, w)
runState s0 = loop s0 . admin where
loop s (Val x) = return (s, x)
loop s (E u) = handleRelay u (loop s) $
\(State t k) -> let s' = t s in s' `seq` loop s' (k s')
newtype Reader e v = Reader (e -> v)
deriving (Typeable, Functor)
getReader :: (Typeable e, Member (Reader e) r) => Eff r e
getReader = send (inj . Reader)
runReader :: Typeable e => Eff (Reader e :> r) w -> e -> Eff r w
runReader m e = loop (admin m) where
loop (Val x) = return x
loop (E u) = handleRelay u loop (\(Reader k) -> loop (k e))
local :: (Typeable e, Member (Reader e) r) =>
(e -> e) -> Eff r a -> Eff r a
local f m = do
e <- f <$> getReader
let loop (Val x) = return x
loop (E u) = interpose u loop (\(Reader k) -> loop (k e))
loop (admin m)
data Writer e v = Writer e v
deriving (Typeable, Functor)
putWriter :: (Typeable e, Member (Writer e) r) => e -> Eff r ()
putWriter e = send $ \f -> inj $ Writer e $ f ()
runWriter :: Typeable e => Eff (Writer e :> r) w -> Eff r (Maybe e, w)
runWriter = loop . admin
where
correctVal f = fmap $ \(x, y) -> (f x, y)
loop (Val x) = return (Nothing, x)
loop (E u) = handleRelay u loop (\(Writer e v) -> correctVal (<|> Just e) $ loop v)
runPusher :: Typeable e => Eff (Writer e :> r) w -> Eff r ([e], w)
runPusher = loop . admin
where
loop (Val x) = return ([], x)
loop (E u) = handleRelay u loop (\(Writer e v) -> (\(es, v') -> (e:es, v')) <$> loop v)