{- | A Go-like EDSL to make working with concurrent in-process code a bit easier to read. This module is expected to be imported qualified as `Go`. $example -} {-# LANGUAGE NoImplicitPrelude #-} module Com.Simatime.Go ( -- * Running and forking Go , run , fork -- * Channels , Channel , chan , read , write ) where import Control.Concurrent ( forkIO , ThreadId ) import Control.Concurrent.STM.TChan ( newTChan , readTChan , writeTChan , TChan ) import GHC.Conc ( STM , atomically ) import Protolude ( IO() , MonadIO(liftIO) , flip , (.) ) type Go = STM type Channel = TChan -- | Runs a Go command in IO. run :: Go a -> IO a run = atomically -- | Starts a background process. fork :: IO () -> IO ThreadId fork = forkIO -- | Make a new channel. chan :: Go (Channel a) chan = newTChan -- | Take from a channel. Blocks until a value is received. read :: Channel a -> Go a read = readTChan -- | Write to a channel. write :: Channel a -> a -> Go () write = writeTChan {- $example A simple example from ghci: >>> import qualified Com.Simatime.Go as Go >>> c <- Go.run Go.chan :: IO (Go.Channel Text) >>> Go.run $ Go.write c "test" >>> Go.run $ Go.read c "test" -}