packages feed

om-fork-0.7.1.6: examples/actor.hs

{-# LANGUAGE LambdaCase #-}

module Main (main) where

import Control.Concurrent (Chan, forkIO, newChan, readChan)
import Control.Monad (void)
import OM.Fork (Responder, call, cast, respond)


{- | Messages that can be sent to the actor. -}
data MyMsg
  = ReverseEcho String (Responder String)
    {- ^ A blocking message. Responds with a String -}
  | Print String
    {- ^ A non-blocking message. -}
  | GetState (Responder Int)
    {- ^ Another blocking message. Responds with an Int -}


{- | The "state" is just a count of how many messages we've seen so far. -}
actorLoop :: Int -> Chan MyMsg -> IO void
actorLoop state chan = do
  readChan chan >>= \case
      ReverseEcho str responder ->
        void $ respond responder (reverse str)
      Print str ->
        putStrLn ("Printeded in background by actor thread: " <> str)
      GetState responder ->
        void $ respond responder state
  actorLoop (succ state) chan


main :: IO ()
main = do
  {- `Chan a` is an instance of `Actor` -}
  chan <- newChan
  void . forkIO $ actorLoop 0 chan

  {- | Notice that the result of this `call` is a String. -}
  putStrLn =<< call chan (ReverseEcho "hello world")
  cast chan (Print "foo")

  {- | Notice that the result of this `call` is an Int. -}
  actorState <- call chan GetState
  print (actorState * 2)