-- | A complete example for the library module Main where import GHC.Stack import Control.Eff import Control.Monad import Data.Dynamic import Control.Eff.Concurrent import Control.Eff.Concurrent.Protocol.EffectfulServer import qualified Control.Exception as Exc import qualified Data.Text as T import Control.DeepSeq import Data.Type.Pretty data TestProtocol deriving Typeable type instance ToPretty TestProtocol = PutStr "test" data instance Pdu TestProtocol x where SayHello :: String -> Pdu TestProtocol ('Synchronous Bool) Shout :: String -> Pdu TestProtocol 'Asynchronous Terminate :: Pdu TestProtocol ('Synchronous ()) TerminateError :: String -> Pdu TestProtocol ('Synchronous ()) deriving (Typeable) instance NFData (Pdu TestProtocol x) where rnf (SayHello s) = rnf s rnf (Shout s) = rnf s rnf Terminate = () rnf (TerminateError s) = rnf s data MyException = MyException deriving Show instance Exc.Exception MyException deriving instance Show (Pdu TestProtocol x) main :: IO () main = defaultMain example mainProcessSpawnsAChildAndReturns :: HasCallStack => Eff InterruptableProcEff () mainProcessSpawnsAChildAndReturns = void (spawn "some child" (void receiveAnyMessage)) example:: HasCallStack => Eff InterruptableProcEff () example = do me <- self logInfo (T.pack ("I am " ++ show me)) server <- testServerLoop logInfo (T.pack ("Started server " ++ show server)) let go = do lift (putStr "Enter something: ") x <- lift getLine case x of ('K' : rest) -> do call server (TerminateError rest) go ('S' : _) -> do call server Terminate go ('C' : _) -> do cast server (Shout x) go ('R' : rest) -> do replicateM_ (read rest) (cast server (Shout x)) go ('q' : _) -> logInfo "Done." _ -> do res <- call server (SayHello x) logInfo (T.pack ("Result: " ++ show res)) go go testServerLoop :: Eff InterruptableProcEff (Endpoint TestProtocol) testServerLoop = start (genServer (const id) handleReq "test-server-1") where handleReq :: GenServerId TestProtocol -> Event TestProtocol -> Eff InterruptableProcEff () handleReq _myId (OnCall ser orig cm) = case cm of Terminate -> do me <- self logInfo (T.pack (show me ++ " exiting")) sendReply ser orig () interrupt NormalExitRequested TerminateError e -> do me <- self logInfo (T.pack (show me ++ " exiting with error: " ++ e)) sendReply ser orig () interrupt (ErrorInterrupt e) SayHello mx -> case mx of "e1" -> do me <- self logInfo (T.pack (show me ++ " raising an error")) interrupt (ErrorInterrupt "No body loves me... :,(") "e2" -> do me <- self logInfo (T.pack (show me ++ " throwing a MyException ")) void (lift (Exc.throw MyException)) "self" -> do me <- self logInfo (T.pack (show me ++ " casting to self")) cast (asEndpoint @TestProtocol me) (Shout "from me") sendReply ser orig False "stop" -> do me <- self logInfo (T.pack (show me ++ " stopping me")) sendReply ser orig False interrupt (ErrorInterrupt "test error") x -> do me <- self logInfo (T.pack (show me ++ " Got Hello: " ++ x)) sendReply ser orig (length x > 3) handleReq _myId (OnCast (Shout x)) = do me <- self logInfo (T.pack (show me ++ " Shouting: " ++ x)) handleReq _myId (OnInterrupt msg) = do me <- self logInfo (T.pack (show me ++ " is exiting: " ++ show msg)) logProcessExit msg interrupt msg handleReq _myId wtf = do me <- self logCritical (T.pack (show me ++ " WTF: " ++ show wtf))