packages feed

drama-0.2.0.0: examples/workers.hs

{-# LANGUAGE BlockArguments #-}

module Main (main) where

import Control.Monad (replicateM, when)
import Data.Function ((&))
import Drama


main :: IO ()
main = run do
  -- Spawn `fib` actor, which starts waiting for requests.
  fibAddress <- spawn fib

  -- Request fibonacci numbers from `fib`. `fib` will spawn three `fibWorker`s
  -- to do all the work in the background, and then send `main` their results
  -- once they finish.
  myAddress <- here
  [200, 400, 600] & mapM_ \n -> send fibAddress (myAddress, n)

  -- Receive results sent back from the `fibWorker`s, and print them to the
  -- console.
  replicateM 3 receive >>= mapM_ \(n, f) ->
    liftIO $ putStrLn ("Fibonacci number " <> show n <> " is " <> show f)

  -- Tell `fib` to stop.
  send fibAddress (myAddress, -1)

  -- Wait for `fib` to stop before exiting.
  wait


-- | Actor which immediately spawns and delegates to "worker" actors.
fib :: Actor (Address (Int, Integer), Int) ()
fib = do
  (responseAddress, n) <- receive
  when (n >= 0) do
    spawn_ (fibWorker responseAddress n)
    fib


-- | "Worker" actor responsible for doing the real, time-consuming work.
fibWorker :: Address (Int, Integer) -> Int -> Actor Void ()
fibWorker responseAddress n = send responseAddress (n, fibs !! n)


-- | Infinite list of fibonacci numbers.
fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)