packages feed

drama-0.1.0.0: src/Drama/Demo.hs

{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE RankNTypes #-}

module Drama.Demo where

import Control.Concurrent (threadDelay)
import Control.Monad (forever)
import Control.Monad.IO.Class (MonadIO (..))
import Drama
import Prelude hiding (log)


main2 :: IO ()
main2 = run do
  loggerAddress <- spawn logger
  _ <- spawn (fizzBuzz loggerAddress)
  wait


logger :: Actor String ()
logger = forever do
  string <- receive
  liftIO $ putStrLn string


fizzBuzz :: Address String -> Actor () ()
fizzBuzz loggerAddress = do
  let log = send loggerAddress

  loop (1 :: Int) \n -> do
    if | n `mod` 15 == 0 -> log "FizzBuzz"
       | n `mod`  3 == 0 -> log "Fizz"
       | n `mod`  5 == 0 -> log "Buzz"
       | otherwise       -> log (show n)

    liftIO $ threadDelay 500_000

    continue (n + 1)


counter :: Actor msg Int
counter = loop 10 \count -> do
  liftIO $ print count
  if count > 0
    then continue (count - 1)
    else exit count


echo :: (forall msg. String -> Actor msg ()) -> Actor () ()
echo log = forever do
  line <- liftIO getLine
  if line == "ping" then
    log "pong"
  else
    log line


add1 :: (forall msg. String -> Actor msg ()) -> Actor (Address Int, Int) ()
add1 log = forever do
  log "[add1] Waiting for request"
  (returnAddress, number) <- receive
  log "[add1] Received request"
  log "[add1] Spawning worker"
  spawn (add1Worker log number returnAddress)


add1Worker :: (forall msg. String -> Actor msg ()) -> Int -> Address Int -> Actor () ()
add1Worker log number returnAddress = do
  log "[add1Worker] Started"
  send returnAddress (number + 1)
  log "[add1Worker] Replied"


program :: Actor Int ()
program = do
  liftIO $ putStrLn "[main] START"

  liftIO $ putStrLn "[main] Spawning logger"
  loggerAddress <- spawn logger

  let log = send loggerAddress

  liftIO $ putStrLn "[main] Spawning echo"
  _ <- spawn (echo log)

  log "[main] Spawning add1"
  add1Address <- spawn (add1 log)

  log "[main] Sending number to add1"
  address <- here
  send add1Address (address, 1)
  two <- receive
  log ("[main] Received response from add1: " <> show two)

  log "[main] FINISH"
  wait


main :: IO ()
main = run program