module Control.Remote.Applicative
(
RemoteApplicative
, command
, procedure
, RunApplicative(runApplicative)
, runWeakApplicative
, runStrongApplicative
, runApplicativeApplicative
) where
import Control.Monad.Trans.Class
import Control.Monad.Trans.State.Strict
import Control.Remote.Monad.Packet.Applicative as A
import qualified Control.Remote.Monad.Packet.Strong as Strong
import Control.Remote.Monad.Packet.Strong (StrongPacket, HStrongPacket(..))
import qualified Control.Remote.Monad.Packet.Weak as Weak
import Control.Remote.Monad.Packet.Weak (WeakPacket)
import Control.Remote.Monad.Types
import Control.Natural
command :: c -> RemoteApplicative c p ()
command c = RemoteApplicative (Command (pure ()) c)
procedure :: p a -> RemoteApplicative c p a
procedure p = RemoteApplicative (Procedure (pure id) p)
class RunApplicative f where
runApplicative :: (Monad m) => (f c p :~> m) -> (RemoteApplicative c p :~> m)
instance RunApplicative WeakPacket where
runApplicative = runWeakApplicative
instance RunApplicative StrongPacket where
runApplicative = runStrongApplicative
instance RunApplicative ApplicativePacket where
runApplicative = runApplicativeApplicative
runWeakApplicative :: forall m c p . (Applicative m) => (WeakPacket c p :~> m) -> (RemoteApplicative c p :~> m)
runWeakApplicative (Nat f) = nat go
where
go :: forall a . RemoteApplicative c p a -> m a
go (RemoteApplicative (Command g c)) = go (RemoteApplicative g) <* f (Weak.Command c)
go (RemoteApplicative (Procedure g p)) = go (RemoteApplicative g) <*> f (Weak.Procedure p)
go (RemoteApplicative (Pure a)) = pure a
runStrongApplicative :: forall m c p . (Monad m) => (StrongPacket c p :~> m) -> (RemoteApplicative c p :~> m)
runStrongApplicative (Nat f) = nat $ \ (RemoteApplicative p) -> do
(r,HStrongPacket h) <- runStateT (go p) (HStrongPacket id)
f $ h $ Strong.Done
return r
where
go :: forall a . ApplicativePacket c p a -> StateT (HStrongPacket c p) m a
go (Pure a) = return a
go (Command g c) = do
r <- go g
modify (\ (HStrongPacket cs) -> HStrongPacket (cs . Strong.Command c))
return r
go (Procedure g p) = do
r1 <- go g
HStrongPacket cs <- get
put (HStrongPacket id)
r2 <- lift $ f $ cs $ Strong.Procedure $ p
return $ r1 r2
runApplicativeApplicative :: (ApplicativePacket c p :~> m) -> (RemoteApplicative c p :~> m)
runApplicativeApplicative f = nat $ \ (RemoteApplicative m) -> f # m