packages feed

drama-0.3.0.0: examples/workers.hs

{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}

module Main (main) where

import Data.Function ((&))
import Drama


main :: IO ()
main = run_ do
  -- Spawn `fib` process, which starts waiting for requests.
  fibAddr <- spawn fib

  let ns = [200, 400, 600]

  -- 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.
  fs <- mapM (call fibAddr . GetFibNumber) ns

  fs & mapM_ \(n, f) ->
    liftIO $ putStrLn ("Fibonacci number " <> show n <> " is " <> show f)


data FibMsg res where
  GetFibNumber :: Int -> FibMsg (Int, Integer)


-- | Process which immediately spawns and delegates to "worker" processes.
fib :: Server FibMsg ()
fib = forever do
  envelope <- receive
  spawn_ (fibWorker envelope)


-- | "Worker" process responsible for doing the real, time-consuming work. Dies
-- after sending its result to the return address.
fibWorker :: Envelope FibMsg -> Process NoMsg ()
fibWorker = handle \case
  GetFibNumber n -> pure (n, fibs !! n)


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