-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Message passing concurrency as extensible-effect
--
-- Please see the README on GitHub at
-- https://github.com/sheyll/extensible-effects-concurrent#readme
@package extensible-effects-concurrent
@version 0.1.2.2
-- | The message passing effect.
--
-- This module describes an abstract message passing effect, and a
-- process effect, mimicking Erlang's process and message semantics.
--
-- An implementation of a handler for these effects can be found in
-- Dispatcher.
module Control.Eff.Concurrent.MessagePassing
-- | Each process is identified by a single process id, that stays constant
-- throughout the life cycle of a process. Also, message sending relies
-- on these values to address messages to processes.
newtype ProcessId
ProcessId :: Int -> ProcessId
[_fromProcessId] :: ProcessId -> Int
fromProcessId :: Iso' ProcessId Int
-- | The process effect is the basis for message passing concurrency. This
-- binds the semantics of a process with a process-id, and some process
-- flags, and the ability to leave a process early with an error.
data Process b
[SelfPid] :: Process ProcessId
[TrapExit] :: Bool -> Process ()
[GetTrapExit] :: Process Bool
[RaiseError] :: String -> Process b
-- | Returns the ProcessId of the current process.
self :: Member Process r => Eff r ProcessId
-- | Set the flag that controls a process reaction to exit messages from
-- linked/monitored processes.
trapExit :: Member Process r => Bool -> Eff r ()
-- | Return the trapExit flag.
getTrapExit :: Member Process r => Eff r Bool
-- | Thrown an error, can be caught by catchProcessError.
raiseError :: Member Process r => String -> Eff r b
-- | Catch and handle an error raised by raiseError. Works
-- independent of the handler implementation.
catchProcessError :: forall r w. Member Process r => (String -> Eff r w) -> Eff r w -> Eff r w
-- | Like catchProcessError it catches raiseError, but
-- instead of invoking a user provided handler, the result is wrapped
-- into an Either.
ignoreProcessError :: (HasCallStack, Member Process r) => Eff r a -> Eff r (Either String a)
-- | An effect for sending and receiving messages.
data MessagePassing b
-- | Send a message to a process addressed by the ProcessId. Sending
-- a message should **always succeed** and return **immediately**, even
-- if the destination process does not exist, or does not accept messages
-- of the given type.
[SendMessage] :: Typeable m => ProcessId -> m -> MessagePassing Bool
-- | Receive a message. This should block until an a message was received.
-- The pure function may convert the incoming message into something, and
-- the result is returned as Message value. Another reason why
-- this function returns, is if a process control message was sent to the
-- process. This can only occur from inside the runtime system, aka the
-- effect handler implementation. (Currently there is one in
-- Dispatcher.)
[ReceiveMessage] :: forall e m. (Typeable m, Typeable (Message m)) => (m -> e) -> MessagePassing (Message e)
-- | When a process invokes receiveMessage a value of this type is
-- returned. There are more reasons that receiveMessage might
-- return, one is that a message was sent to the process, another might
-- be that in internal, handler specific, event occurred for which the
-- process should wake-up.
data Message m
[ProcessControlMessage] :: String -> Message m
[Message] :: m -> Message m
-- | Send a message to a process addressed by the ProcessId. @see
-- SendMessage.
sendMessage :: forall o r. (HasCallStack, Member MessagePassing r, Typeable o) => ProcessId -> o -> Eff r Bool
-- | Block until a message was received. Expect a message of the type
-- annotated by the Proxy. Depending on trapExit, this will
-- raiseError. @see ReceiveMessage.
receiveMessage :: forall o r. (HasCallStack, Member MessagePassing r, Member Process r, Typeable o) => Proxy o -> Eff r (Message o)
instance Data.Traversable.Traversable Control.Eff.Concurrent.MessagePassing.Message
instance Data.Foldable.Foldable Control.Eff.Concurrent.MessagePassing.Message
instance GHC.Classes.Ord m => GHC.Classes.Ord (Control.Eff.Concurrent.MessagePassing.Message m)
instance GHC.Classes.Eq m => GHC.Classes.Eq (Control.Eff.Concurrent.MessagePassing.Message m)
instance GHC.Show.Show m => GHC.Show.Show (Control.Eff.Concurrent.MessagePassing.Message m)
instance GHC.Base.Functor Control.Eff.Concurrent.MessagePassing.Message
instance GHC.Real.Real Control.Eff.Concurrent.MessagePassing.ProcessId
instance GHC.Real.Integral Control.Eff.Concurrent.MessagePassing.ProcessId
instance GHC.Enum.Enum Control.Eff.Concurrent.MessagePassing.ProcessId
instance GHC.Num.Num Control.Eff.Concurrent.MessagePassing.ProcessId
instance GHC.Enum.Bounded Control.Eff.Concurrent.MessagePassing.ProcessId
instance GHC.Classes.Ord Control.Eff.Concurrent.MessagePassing.ProcessId
instance GHC.Classes.Eq Control.Eff.Concurrent.MessagePassing.ProcessId
instance GHC.Read.Read Control.Eff.Concurrent.MessagePassing.ProcessId
instance GHC.Show.Show Control.Eff.Concurrent.MessagePassing.ProcessId
-- | Type safe server API processes
module Control.Eff.Concurrent.GenServer
-- | This data family defines an API implemented by a server. The first
-- parameter is the API index and the second parameter (the *
-- -> *)
data Synchronicity
Synchronous :: Type -> Synchronicity
Asynchronous :: Synchronicity
data ApiHandler p r e
ApiHandler :: (Typeable p, Typeable (Api p 'Asynchronous), HasCallStack) => Api p 'Asynchronous -> Eff r e -> (forall x. (Typeable p, Typeable (Api p ( 'Synchronous x)), Typeable x, HasCallStack) => Api p ( 'Synchronous x) -> (x -> Eff r Bool) -> Eff r e) -> (Typeable p, HasCallStack) => String -> Eff r () -> ApiHandler p r e
newtype Server genServerModule
Server :: ProcessId -> Server genServerModule
[_fromServer] :: Server genServerModule -> ProcessId
fromServer :: forall genServerModule_agQU genServerModule_ah0L. Iso (Server genServerModule_agQU) (Server genServerModule_ah0L) ProcessId ProcessId
proxyAsServer :: proxy genServerModule -> ProcessId -> Server genServerModule
asServer :: forall genServerModule. ProcessId -> Server genServerModule
cast :: forall r o. (HasCallStack, Member MessagePassing r, Typeable o, Typeable (Api o 'Asynchronous)) => Server o -> Api o 'Asynchronous -> Eff r Bool
cast_ :: forall r o. (HasCallStack, Member MessagePassing r, Typeable o, Typeable (Api o 'Asynchronous)) => Server o -> Api o 'Asynchronous -> Eff r ()
call :: forall result genServerModule r. (Member MessagePassing r, Member Process r, Typeable genServerModule, Typeable (Api genServerModule ( 'Synchronous result)), Typeable result, HasCallStack) => Server genServerModule -> Api genServerModule ( 'Synchronous result) -> Eff r (Message result)
serve :: forall r p e. (Typeable p, Member MessagePassing r, Member Process r, HasCallStack) => ApiHandler p r e -> Eff r (Message e)
serve_ :: forall r p. (Typeable p, Member MessagePassing r, Member Process r, HasCallStack) => ApiHandler p r () -> Eff r ()
unhandledCallError :: (Show (Api p ( 'Synchronous x)), Typeable p, Typeable (Api p ( 'Synchronous x)), Typeable x, HasCallStack, Member Process r) => Api p ( 'Synchronous x) -> (x -> Eff r Bool) -> Eff r e
unhandledCastError :: (Show (Api p 'Asynchronous), Typeable p, Typeable (Api p 'Asynchronous), HasCallStack, Member Process r) => Api p 'Asynchronous -> Eff r e
instance GHC.Classes.Ord (Control.Eff.Concurrent.GenServer.Server genServerModule)
instance GHC.Classes.Eq (Control.Eff.Concurrent.GenServer.Server genServerModule)
instance GHC.Read.Read (Control.Eff.Concurrent.GenServer.Server genServerModule)
instance Data.Typeable.Internal.Typeable genServerModule => GHC.Show.Show (Control.Eff.Concurrent.GenServer.Server genServerModule)
-- | Add-ons to Exception
module Control.Eff.ExceptionExtra
-- | Catch an exception and return it in an Either.
try :: forall e r a. Member (Exc e) r => Eff r a -> Eff r (Either e a)
-- | Lift an IO action and catch all error using try then wrap the
-- Exception using a given wrapper function and rethrow it using
-- throwError.
liftRethrow :: forall e r a. (Exception e, SetMember Lift (Lift IO) r, Member (Exc e) r) => (SomeException -> e) -> IO a -> Eff r a
-- | Run an effect with exceptions like runError and rethrow it as
-- SomeException using throw
runErrorRethrowIO :: forall e r a. (Exception e, SetMember Lift (Lift IO) r) => Eff (Exc e : r) a -> Eff r a
module Control.Eff.Interactive
data Interaction a
[PrintLine] :: String -> Interaction ()
[ReadLine] :: (String -> a) -> Interaction a
[Step] :: Interaction ()
printLine :: (Member (Program Interaction) r, HasCallStack) => String -> Eff r ()
printStep :: (Member (Program Interaction) r, HasCallStack) => String -> Eff r ()
promptStep :: (Member (Program Interaction) r, HasCallStack) => String -> (String -> a) -> Eff r a
step :: (Member (Program Interaction) r, HasCallStack) => Eff r ()
class Interactive f
singleSteps :: (Interactive f, Member (Program Interaction) r, HasCallStack) => f a -> Eff r a
interactiveProgram :: (HasCallStack, Member (Program Interaction) r, Interactive f) => Eff (Program f : r) a -> Eff r a
runInteractionIOE :: (SetMember Lift (Lift IO) r, HasCallStack) => Eff (Program Interaction : r) a -> Eff r a
runInteractionIO :: Eff '[Program Interaction, Lift IO] a -> IO a
-- | An extensible effect that wraps MonadLog into an extensible
-- effect.
module Control.Eff.Log
-- | Handle Logs effects using LoggingT Handlers.
handleLogsWith :: forall m r message a. (Monad m, SetMember Lift (Lift m) r) => Eff (Logs message : r) a -> (forall b. (Handler m message -> m b) -> m b) -> Eff r a
-- | The Effect type to wrap MonadLog. This is a
data Logs message a
[LogMessageFree] :: (forall n. Monoid n => (message -> n) -> n) -> Logs message ()
-- | Effectful version of the strange logMessageFree
-- function.
logMessageFreeEff :: Member (Logs message) r => (forall n. Monoid n => (message -> n) -> n) -> Eff r ()
-- | Effectful version of the logMessage function.
logMsg :: Member (Logs m) r => m -> Eff r ()
-- | Input queue for a concurrent logger.
data LogChannel message
-- | Enqueue a log message into a log channel
logChannelPutIO :: LogChannel message -> message -> IO ()
-- | Send the log messages to a LogChannel.
forwardLogsToChannel :: forall r message a. (SetMember Lift (Lift IO) r) => LogChannel message -> Eff (Logs message : r) a -> Eff r a
-- | Fork LogChannel backed by a process that repeatedly receives
-- log messages sent by forwardLogstochannel or
-- logChannelPutIO. The process logs by invoken the given IO
-- action. To stop and terminate a LogChannel invoke
-- joinLogChannel.
forkLogChannel :: forall message. (message -> IO ()) -> Maybe message -> IO (LogChannel message)
-- | Close a log channel. Subsequent loggin requests will no be handled any
-- more.
joinLogChannel :: Maybe message -> LogChannel message -> IO ()
-- | Wrap LogChannel creation and destruction around a monad action
-- in brackety manner.
logChannelBracket :: Maybe message -> Maybe message -> (LogChannel message -> IO a) -> LoggingT message IO a
-- | Implement Erlang style message passing concurrency.
--
-- This handles the MessagePassing and Process effects,
-- using TQueues and forkIO.
--
-- This aims to be a pragmatic implementation, so even logging is
-- supported.
--
-- At the core is a main process that enters runMainProcess
-- and creates all of the internal state stored in TVars to manage
-- processes with message queues.
--
-- The Eff handler for Process and MessagePassing
-- use are implemented and available through spawn.
--
-- spawn uses forkFinally and TQueues and tries to
-- catch most exceptions.
module Control.Eff.Concurrent.Dispatcher
-- | This is the main entry point to running a message passing concurrency
-- application. This function takes a ProcIO effect and a
-- LogChannel for concurrent logging.
runMainProcess :: Eff ProcIO a -> LogChannel String -> IO a
-- | Start the message passing concurrency system then execute a
-- ProcIO effect. All logging is sent to standard output.
defaultMain :: Eff ProcIO a -> IO a
spawn :: HasDispatcherIO r => Eff ProcIO () -> Eff r ProcessId
-- | A sum-type with errors that can occur when dispatching messages.
data DispatcherError
-- | A process message queue contained a bad message and the Dynamic
-- value could not be converted to the expected value using
-- fromDynamic.
UnhandledMessageReceived :: Dynamic -> ProcessId -> DispatcherError
-- | No ProcessInfo was found for a ProcessId during internal
-- processing. NOTE: This is **ONLY** caused by internal errors, probably
-- by an incorrect MessagePassing handler in this module.
-- **Sending a message to a process ALWAYS succeeds!** Even if the
-- process does not exist.
ProcessNotFound :: ProcessId -> DispatcherError
-- | A process called raiseError.
ProcessException :: String -> ProcessId -> DispatcherError
-- | An action was not performed while the dispatcher was exiting.
DispatcherShuttingDown :: DispatcherError
-- | SomeException was caught while dispatching messages.
LowLevelIOException :: SomeException -> DispatcherError
-- | The concrete list of Effects for this scheduler implementation.
-- @see HasDispatcherIO
type DispatcherIO = '[Exc DispatcherError, Reader DispatcherVar, Logs String, Lift IO]
-- | An alias for the constraints for the effects essential to this
-- dispatcher implementation, i.e. these effects allow spawning
-- new Processes. @see DispatcherIO
type HasDispatcherIO r = (HasCallStack, SetMember Lift (Lift IO) r, Member (Exc DispatcherError) r, Member (Logs String) r, Member (Reader DispatcherVar) r)
-- | The concrete list of Effects that provide MessagePassing
-- and Processes ontop of DispatcherIO
type ProcIO = ConsProcIO DispatcherIO
instance GHC.Show.Show Control.Eff.Concurrent.Dispatcher.DispatcherError
instance Control.Monad.Log.MonadLog GHC.Base.String (Control.Eff.Eff Control.Eff.Concurrent.Dispatcher.ProcIO)
instance GHC.Exception.Exception Control.Eff.Concurrent.Dispatcher.DispatcherError
instance GHC.Show.Show Control.Eff.Concurrent.Dispatcher.ProcessInfo
-- | Observer Effects
--
-- This module supports the implementation of observers and observables.
-- One more concrete perspective might be to understand observers as
-- event listeners and observables as event sources. The tools in this
-- module are tailored towards Api endpoints
module Control.Eff.Concurrent.Observer
-- | An Api index that support observation of the another Api
-- that is Observable.
class (Typeable p, Observable o) => Observer p o
-- | Wrap the Observation and the ProcessId (i.e. the
-- Server) that caused the observation into a Api value
-- that the Observable understands.
observationMessage :: Observer p o => Server o -> Observation o -> Api p 'Asynchronous
-- | An Api index that supports registration and de-registration of
-- Observers.
class (Typeable o, Typeable (Observation o)) => Observable o where {
data family Observation o;
}
-- | Return the Api value for the cast_ that registeres an
-- observer
registerObserverMessage :: Observable o => SomeObserver o -> Api o 'Asynchronous
-- | Return the Api value for the cast_ that de-registeres an
-- observer
forgetObserverMessage :: Observable o => SomeObserver o -> Api o 'Asynchronous
-- | Send an Observation to an Observer
notifyObserver :: (Member Process r, Member MessagePassing r, Observable o, Observer p o, HasCallStack) => Server p -> Server o -> Observation o -> Eff r ()
-- | Send the registerObserverMessage
registerObserver :: (Member Process r, Member MessagePassing r, Observable o, Observer p o, HasCallStack) => Server p -> Server o -> Eff r ()
-- | Send the forgetObserverMessage
forgetObserver :: (Member Process r, Member MessagePassing r, Observable o, Observer p o) => Server p -> Server o -> Eff r ()
-- | An existential wrapper around a Server of an Observer.
-- Needed to support different types of observers to observe the same
-- Observable in a general fashion.
data SomeObserver o
[SomeObserver] :: (Show (Server p), Typeable p, Observer p o) => Server p -> SomeObserver o
-- | Send an Observation to SomeObserver.
notifySomeObserver :: (Member Process r, Member MessagePassing r, Observable o, HasCallStack) => Server o -> Observation o -> SomeObserver o -> Eff r ()
-- | Internal state for manageobservers
data Observers o
-- | Keep track of registered Observers Observers can be added and
-- removed, and an Observation can be sent to all registerd
-- observers at once.
manageObservers :: Eff (State (Observers o) : r) a -> Eff r a
-- | Add an Observer to the Observers managed by
-- manageObservers.
addObserver :: (Member MessagePassing r, Member (State (Observers o)) r, Observable o) => SomeObserver o -> Eff r ()
-- | Delete an Observer from the Observers managed by
-- manageObservers.
removeObserver :: (Member MessagePassing r, Member (State (Observers o)) r, Observable o) => SomeObserver o -> Eff r ()
-- | Send an Observation to all SomeObservers in the
-- Observers state.
notifyObservers :: forall o r. (Observable o, Member MessagePassing r, Member Process r, Member (State (Observers o)) r) => Observation o -> Eff r ()
-- | An Observer that dispatches the observations to an effectful
-- callback.
data CallbackObserver o
-- | Start a new process for an Observer that dispatches all
-- observations to an effectful callback.
spawnCallbackObserver :: forall o r. (HasDispatcherIO r, Typeable o, Show (Observation o), Observable o) => (Server o -> Observation o -> Eff ProcIO Bool) -> Eff r (Server (CallbackObserver o))
instance GHC.Show.Show (Control.Eff.Concurrent.Observer.SomeObserver o)
instance GHC.Show.Show (Control.Eff.Concurrent.Observer.Observation o) => GHC.Show.Show (Control.Eff.Concurrent.GenServer.Api (Control.Eff.Concurrent.Observer.CallbackObserver o) r)
instance Control.Eff.Concurrent.Observer.Observable o => Control.Eff.Concurrent.Observer.Observer (Control.Eff.Concurrent.Observer.CallbackObserver o) o
instance GHC.Classes.Ord (Control.Eff.Concurrent.Observer.SomeObserver o)
instance GHC.Classes.Eq (Control.Eff.Concurrent.Observer.SomeObserver o)