module Control.Monad.Register.Basic
( evalRegister
, evalRegisterBasic
) where
import Control.Monad
import Control.Monad.State
import Control.Monad.RWS
import Data.List
import Prelude hiding ((.), id)
import Control.Monad.Restricted
import Control.Monad.Register
import Control.Monad.ExtRef
type Register m
= RWST (m () -> m ()) (MonadMonoid m, Command -> MonadMonoid m) () m
instance NewRef m => MonadRegister (Register m) where
type EffectM (Register m) = m
liftEffectM = lift
toReceive_ r int = do
rr <- ask
unreg <- lift $ int $ rr . r
tell $ t2 unreg
return unreg
toSend_ init rb fb = do
rr <- ask
b <- lift rb
v <- case init of
False -> return $ Left b
True -> lift $ do
(c, (), (s1, ureg1)) <- runRWST (fb b) rr ()
((), (s2, ureg2)) <- execRWST c rr ()
runMonadMonoid $ s1 `mappend` s2
return $ Right [(b, (c, s1, s2, ureg1, ureg2))]
memoref <- lift $ newRef' v
tell $ t1 $ do
b <- rb
join $ runMorphD memoref $ StateT $ \memo -> case memo of
Left b' | b' == b -> return (return (), memo)
Right ((b', (_, s1, s2, _, _)): _) | b' == b ->
return (runMonadMonoid $ s1 `mappend` s2, memo)
_ -> do
case memo of
Right ((_, (_, _, _, ureg1, ureg2)): _) ->
runMonadMonoid $ ureg1 Block `mappend` ureg2 Kill
_ -> return ()
(c, (), (s1, ureg1)) <- case filter ((== b) . fst) $ either (const []) id memo of
((_, (c, s1, _, ureg1, _)): _) -> do
runMonadMonoid $ ureg1 Unblock
return (c, (), (s1, ureg1))
_ -> runRWST (fb b) rr ()
((), (s2, ureg2)) <- execRWST c rr ()
let memo' = Right $ (:) (b, (c, s1, s2, ureg1, ureg2)) $ filter ((/= b) . fst) $ either (const []) id memo
return (runMonadMonoid $ s1 `mappend` s2, memo')
t1 m = (MonadMonoid m, mempty)
t2 m = (mempty, MonadMonoid . m)
evalRegister :: forall k a . (NewRef k, ExtRef k, MonadIO k, SafeIO k)
=> (forall t . (MonadTrans t, MonadRegister (t k), MonadIO (t k)
, ExtRef (t k), Ref (t k) ~ Ref k, EffectM (t k) ~ k, SafeIO (t k)) => t k a)
-> (k () -> k ())
-> k a
evalRegister m = evalRegister_ m
evalRegisterBasic
:: forall k a . NewRef k
=> (forall t . (MonadTrans t, MonadRegister (t k)) => t k a)
-> (k () -> k ())
-> k a
evalRegisterBasic m = evalRegister_ m
evalRegister_
:: NewRef k
=> (Register k a)
-> (k () -> k ())
-> k a
evalRegister_ m ch = do
vx <- newRef' $ error "evalRegister"
(a, (), (reg, _)) <- runRWST m (ch . (>> join (runMorphD vx get))) ()
runMorphD vx $ put $ runMonadMonoid reg
return a