-- 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.2.0.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
-- ForkIOScheduler.
module Control.Eff.Concurrent.Process
-- | 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
-- effect describes an interface for concurrent, communicating isolated
-- processes identified uniquely by a process-id.
--
-- Processes can raise exceptions that can be caught, exit gracefully or
-- with an error, or be killed by other processes, with the option of
-- ignoring the shutdown request.
--
-- Process Scheduling is implemented in different modules. All scheduler
-- implementations should follow some basic rules:
--
--
-- - fair scheduling
-- - sending a message does not block
-- - receiving a message does block
-- - spawning a child blocks only a very moment
-- - a newly spawned process shall be scheduled before the parent
-- process after
-- - the spawn
-- - when the first process exists, all process should be killed
-- immediately
--
data Process (r :: [Type -> Type]) b
-- | Return the current ProcessId
[SelfPid] :: Process r (ResumeProcess ProcessId)
-- | Start a new process, the new process will execute an effect, the
-- function will return immediately with a ProcessId.
[Spawn] :: Eff (Process r : r) () -> Process r (ResumeProcess ProcessId)
-- | Process exit, this is the same as if the function that was applied to
-- a spawn function returned.
[Shutdown] :: Process r a
-- | Exit the process due to an error, this cannot be caught.
[ExitWithError] :: String -> Process r b
-- | Raise an error, that can be handled.
[RaiseError] :: String -> Process r b
-- | Request that another a process exits. The targeted process is
-- interrupted and gets a ShutdownRequested, the target process
-- may decide to ignore the shutdown requests.
[SendShutdown] :: ProcessId -> Process r (ResumeProcess Bool)
-- | 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] :: ProcessId -> Dynamic -> Process r (ResumeProcess 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 ProcessMessage 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 ForkIOScheduler.)
[ReceiveMessage] :: Process r (ResumeProcess Dynamic)
-- | Cons Process onto a list of effects.
type ConsProcess r = Process r : r
-- | Every Process action returns it's actual result wrapped in this
-- type. It will allow to signal errors as well as pass on normal results
-- such as incoming messages.
data ResumeProcess v
-- | The process is required to exit.
[ShutdownRequested] :: ResumeProcess v
-- | The process is required to exit from an error condition, that cannot
-- be recovered from.
[OnError] :: String -> ResumeProcess v
-- | The process may resume to do work, using the given result.
[ResumeWith] :: a -> ResumeProcess a
-- | This indicates that the action did not complete, and maybe retried
[RetryLastAction] :: ResumeProcess v
-- | Every function for Process things needs proxy for the low-level
-- effect list depending on the scheduler implementation. I don't know a
-- smarter way yet to do this.
data SchedulerProxy :: [Type -> Type] -> Type
[SchedulerProxy] :: SchedulerProxy q
-- | Return a SchedulerProxy for a Process effect.
thisSchedulerProxy :: Eff (Process r : r) (SchedulerProxy r)
-- | Execute a and action and resume the process, retry the action,
-- shutdown the process or return an error.
yieldAndCatchProcess :: forall q r v. (SetMember Process (Process q) r, HasCallStack) => SchedulerProxy q -> Eff r (ResumeProcess v) -> Eff r (Either String v)
-- | Send a message to a process addressed by the ProcessId. See
-- SendMessage.
sendMessage :: forall r q. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> ProcessId -> Dynamic -> Eff r Bool
-- | Start a new process, the new process will execute an effect, the
-- function will return immediately with a ProcessId.
spawn :: forall r q. (HasCallStack, SetMember Process (Process q) r) => Eff (Process q : q) () -> Eff r ProcessId
-- | Block until a message was received.
receiveMessage :: forall r q. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> Eff r Dynamic
-- | Receive and cast the message to some Typeable instance.
receiveMessageAs :: forall a r q. (HasCallStack, Typeable a, SetMember Process (Process q) r) => SchedulerProxy q -> Eff r a
-- | Enter a loop to receive messages and pass them to a callback, until
-- the function returns False.
receiveLoop :: forall r q. (SetMember Process (Process q) r, HasCallStack) => SchedulerProxy q -> (Either (Maybe String) Dynamic -> Eff r ()) -> Eff r ()
-- | Returns the ProcessId of the current process.
self :: (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> Eff r ProcessId
-- | Send a message to a process addressed by the ProcessId. See
-- SendMessage.
sendShutdown :: forall r q. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> ProcessId -> Eff r Bool
-- | Exit the process with an error.
exitWithError :: forall r q a. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> String -> Eff r a
-- | Exit the process.
exitNormally :: forall r q a. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> Eff r a
-- | Thrown an error, can be caught by catchRaisedError.
raiseError :: forall r q b. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> String -> Eff r b
-- | Catch and handle an error raised by raiseError. Works
-- independent of the handler implementation.
catchRaisedError :: forall r q w. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> (String -> Eff r w) -> Eff r w -> Eff r w
-- | Like catchRaisedError it catches raiseError, but instead
-- of invoking a user provided handler, the result is wrapped into an
-- Either.
ignoreProcessError :: (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> Eff r a -> Eff r (Either String a)
instance GHC.Real.Real Control.Eff.Concurrent.Process.ProcessId
instance GHC.Real.Integral Control.Eff.Concurrent.Process.ProcessId
instance GHC.Enum.Enum Control.Eff.Concurrent.Process.ProcessId
instance GHC.Num.Num Control.Eff.Concurrent.Process.ProcessId
instance GHC.Enum.Bounded Control.Eff.Concurrent.Process.ProcessId
instance GHC.Classes.Ord Control.Eff.Concurrent.Process.ProcessId
instance GHC.Classes.Eq Control.Eff.Concurrent.Process.ProcessId
instance Data.Traversable.Traversable Control.Eff.Concurrent.Process.ResumeProcess
instance GHC.Classes.Ord v => GHC.Classes.Ord (Control.Eff.Concurrent.Process.ResumeProcess v)
instance GHC.Classes.Eq v => GHC.Classes.Eq (Control.Eff.Concurrent.Process.ResumeProcess v)
instance GHC.Show.Show v => GHC.Show.Show (Control.Eff.Concurrent.Process.ResumeProcess v)
instance GHC.Base.Functor Control.Eff.Concurrent.Process.ResumeProcess
instance Data.Foldable.Foldable Control.Eff.Concurrent.Process.ResumeProcess
instance GHC.Read.Read Control.Eff.Concurrent.Process.ProcessId
instance GHC.Show.Show Control.Eff.Concurrent.Process.ProcessId
-- | Type safe server API processes
module Control.Eff.Concurrent.Api
-- | 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
newtype Server api
Server :: ProcessId -> Server api
[_fromServer] :: Server api -> ProcessId
fromServer :: forall api_ahB6 api_ahLz. Iso (Server api_ahB6) (Server api_ahLz) ProcessId ProcessId
proxyAsServer :: proxy api -> ProcessId -> Server api
asServer :: forall api. ProcessId -> Server api
instance forall k (api :: k). GHC.Classes.Ord (Control.Eff.Concurrent.Api.Server api)
instance forall k (api :: k). GHC.Classes.Eq (Control.Eff.Concurrent.Api.Server api)
instance forall k (api :: k). GHC.Read.Read (Control.Eff.Concurrent.Api.Server api)
instance forall k (api :: k). Data.Typeable.Internal.Typeable api => GHC.Show.Show (Control.Eff.Concurrent.Api.Server api)
-- | Type safe server API processes
module Control.Eff.Concurrent.Api.Client
cast :: forall r q o. (HasCallStack, SetMember Process (Process q) r, Typeable o, Typeable (Api o 'Asynchronous)) => SchedulerProxy q -> Server o -> Api o 'Asynchronous -> Eff r ()
castChecked :: forall r q o. (HasCallStack, SetMember Process (Process q) r, Typeable o, Typeable (Api o 'Asynchronous)) => SchedulerProxy q -> Server o -> Api o 'Asynchronous -> Eff r Bool
call :: forall result api r q. (SetMember Process (Process q) r, Typeable api, Typeable (Api api ( 'Synchronous result)), Typeable result, HasCallStack) => SchedulerProxy q -> Server api -> Api api ( 'Synchronous result) -> Eff r result
castRegistered :: (Typeable o, ServesApi o r q) => SchedulerProxy q -> Api o 'Asynchronous -> Eff r ()
callRegistered :: (Typeable reply, ServesApi o r q) => SchedulerProxy q -> Api o ( 'Synchronous reply) -> Eff r reply
callRegisteredA :: forall r q o f reply. (Alternative f, Typeable f, Typeable reply, ServesApi o r q) => SchedulerProxy q -> Api o ( 'Synchronous (f reply)) -> Eff r (f reply)
type ServesApi o r q = (Typeable o, SetMember Process (Process q) r, Member (Reader (Server o)) r)
registerServer :: Server o -> Eff (Reader (Server o) : r) a -> Eff r a
-- | 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 proxy e r a. (Exception e, SetMember Lift (Lift IO) r, SetMember Exc (Exc e) r) => proxy 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
-- | Lift an IO action and catch all errors with try with a pure
-- handler.
liftCatch :: forall e r a. (HasCallStack, Exception e, SetMember Lift (Lift IO) r) => (e -> a) -> IO a -> Eff r a
-- | Lift an IO action and catch all errors with try with an effect
-- handler.
liftCatchEff :: forall e r a. (SetMember Lift (Lift IO) r, HasCallStack, Exception e) => (e -> Eff r a) -> IO a -> Eff r a
-- | Catch Exception thrown by an effect.
liftTry :: forall e r a. (HasCallStack, Exception e, SetMember Lift (Lift IO) r) => Eff r a -> Eff r (Either e 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
-- | Type safe server API processes
module Control.Eff.Concurrent.Api.Server
-- | A record of callbacks requests to a server, serving a specific
-- Api family instance.
data ApiHandler p r
[ApiHandler] :: {_handleCast :: HasCallStack => Api p 'Asynchronous -> Eff r () A cast will not return a result directly. This is used for async methods., _handleCall :: forall x. HasCallStack => Api p ( 'Synchronous x) -> (x -> Eff r Bool) -> Eff r () A call is a blocking operation, the caller is blocked until this handler calls the reply continuation., _handleTerminate :: HasCallStack => Maybe String -> Eff r () This callback is called with @Nothing@ if the process exits peacefully, or @Just "error message..."@ if the process exits with an error. This function is responsible to exit the process if necessary. The default behavior is defined in 'defaultTermination'.} -> ApiHandler p r
-- | Receive messages until the process exits and invoke the callback on
-- each message.
serve :: forall r q p. (Typeable p, SetMember Process (Process q) r, HasCallStack) => SchedulerProxy q -> ApiHandler p r -> Eff r ()
-- | A default handler to use in _handleCall in ApiHandler.
-- It will call raiseError with a nice error message.
unhandledCallError :: forall p x r q. (Show (Api p ( 'Synchronous x)), Typeable p, HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> Api p ( 'Synchronous x) -> (x -> Eff r Bool) -> Eff r ()
-- | A default handler to use in _handleCast in ApiHandler.
-- It will call raiseError with a nice error message.
unhandledCastError :: forall p r q. (Show (Api p 'Asynchronous), Typeable p, HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> Api p 'Asynchronous -> Eff r ()
-- | Exit the process either normally of the error message is
-- Nothing or with exitWithError otherwise.
defaultTermination :: forall q r. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> Maybe String -> Eff r ()
-- | serve two ApiHandlers at once. The first handler is used
-- for termination handling.
serveBoth :: forall r q p1 p2. (Typeable p1, Typeable p2, SetMember Process (Process q) r, HasCallStack) => SchedulerProxy q -> ApiHandler p1 r -> ApiHandler p2 r -> Eff r ()
-- | serve three ApiHandlers at once. The first handler is
-- used for termination handling.
serve3 :: forall r q p1 p2 p3. (Typeable p1, Typeable p2, Typeable p3, SetMember Process (Process q) r, HasCallStack) => SchedulerProxy q -> ApiHandler p1 r -> ApiHandler p2 r -> ApiHandler p3 r -> Eff r ()
-- | The basic building block of the combination of ApiHandlers is
-- this function, which can not only be passed to receiveLoop, but
-- also throws an UnhandledRequest exception if castMessage
-- failed, such that multiple invokation of this function for different
-- ApiHandlers can be tried, by using catchUnhandled.
--
--
-- tryApiHandler px handlers1 message
-- `catchUnhandled`
-- tryApiHandler px handlers2
-- `catchUnhandled`
-- tryApiHandler px handlers3
--
tryApiHandler :: forall r q p. (Typeable p, SetMember Process (Process q) r, HasCallStack) => SchedulerProxy q -> ApiHandler p r -> Dynamic -> Eff (Exc UnhandledRequest : r) ()
-- | An exception that is used by the mechanism that chains together
-- multiple different ApiHandler allowing a single process to
-- implement multiple Apis. This exception is thrown by
-- castMessage. This exception can be caught with
-- catchUnhandled, this way, several distinct ApiHandler
-- can be tried until one fits or until the exitUnhandled
-- is invoked.
data UnhandledRequest
-- | If castMessage failes to cast the message to a Request
-- for a certain ApiHandler it throws an UnhandledRequest
-- exception. That exception is caught by this function and the raw
-- message is given to the handler function. This is the basis for
-- chaining ApiHandlers.
catchUnhandled :: forall r a. (Member (Exc UnhandledRequest) r, HasCallStack) => Eff r a -> (Dynamic -> Eff r a) -> Eff r a
-- | Catch UnhandledRequests and terminate the process with an
-- error, if necessary.
ensureAllHandled :: forall r q. (HasCallStack, SetMember Process (Process q) r) => SchedulerProxy q -> Eff (Exc UnhandledRequest : r) () -> Eff r ()
-- | Cast a Dynamic value, and if that fails, throw an
-- UnhandledRequest error.
castMessage :: forall r a. (HasCallStack, Typeable a, Member (Exc UnhandledRequest) r) => Dynamic -> Eff r a
-- | If an incoming message could not be casted to a Request
-- corresponding to an ApiHandler (e.g. with castMessage)
-- one should use this function to exit the process with a corresponding
-- error.
exitUnhandled :: forall r q. (SetMember Process (Process q) r, HasCallStack) => SchedulerProxy q -> Dynamic -> Eff r ()
-- | 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
[LogMsg] :: message -> Logs message ()
-- | 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 ()
-- | Capture the logs in a Seq.
captureLogs :: Eff (Logs message : r) a -> Eff r (a, Seq message)
-- | Throw away all log messages.
ignoreLogs :: Eff (Logs message : r) a -> Eff r a
-- | 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
-- | A coroutine based, single threaded scheduler for Processes.
module Control.Eff.Concurrent.Process.SingleThreadedScheduler
-- | Execute a Process in the current thread, all child processes
-- spawned by spawn will be executed concurrently using a
-- co-routine based, round-robin scheduler.
schedule :: forall r. Eff (Process r : r) () -> Eff r ()
-- | Execute a Process using schedule on top of Lift
-- IO and Logs String effects.
defaultMain :: HasCallStack => Eff '[Process '[Logs String, Lift IO], Logs String, Lift IO] () -> IO ()
-- | A SchedulerProxy for LoggingAndIo.
singleThreadedIoScheduler :: SchedulerProxy LoggingAndIo
-- | The concrete list of Effects for running this pure scheduler on
-- IO and with string logging.
type LoggingAndIo = '[Logs String, Lift IO]
-- | 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 schedule 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.Process.ForkIOScheduler
-- | This is the main entry point to running a message passing concurrency
-- application. This function takes a Process on top of the
-- SchedulerIO effect and a LogChannel for concurrent
-- logging.
schedule :: Eff (ConsProcess SchedulerIO) () -> LogChannel String -> IO ()
-- | Start the message passing concurrency system then execute a
-- Process on top of SchedulerIO effect. All logging is
-- sent to standard output.
defaultMain :: Eff (ConsProcess SchedulerIO) () -> IO ()
-- | A sum-type with errors that can occur when scheduleing messages.
data SchedulerError
-- | 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 -> SchedulerError
-- | A process called raiseError.
ProcessRaisedError :: String -> SchedulerError
-- | A process called exitWithError.
ProcessExitError :: String -> SchedulerError
-- | A process exits.
ProcessShuttingDown :: SchedulerError
-- | An action was not performed while the scheduler was exiting.
SchedulerShuttingDown :: SchedulerError
-- | The concrete list of Effects for this scheduler implementation.
-- See HasSchedulerIO
type SchedulerIO = '[Reader SchedulerVar, Logs String, Lift IO]
-- | A SchedulerProxy for SchedulerIO
forkIoScheduler :: SchedulerProxy SchedulerIO
-- | An alias for the constraints for the effects essential to this
-- scheduler implementation, i.e. these effects allow spawning new
-- Processes. See SchedulerIO
type HasSchedulerIO r = (HasCallStack, SetMember Lift (Lift IO) r, Member (Logs String) r, Member (Reader SchedulerVar) r)
instance GHC.Show.Show Control.Eff.Concurrent.Process.ForkIOScheduler.SchedulerError
instance GHC.Exception.Exception Control.Eff.Concurrent.Process.ForkIOScheduler.SchedulerError
instance GHC.Show.Show Control.Eff.Concurrent.Process.ForkIOScheduler.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.Api.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 :: (SetMember Process (Process q) r, Observable o, Observer p o, HasCallStack) => SchedulerProxy q -> Server p -> Server o -> Observation o -> Eff r ()
-- | Send the registerObserverMessage
registerObserver :: (SetMember Process (Process q) r, Observable o, Observer p o, HasCallStack) => SchedulerProxy q -> Server p -> Server o -> Eff r ()
-- | Send the forgetObserverMessage
forgetObserver :: (SetMember Process (Process q) r, Observable o, Observer p o) => SchedulerProxy q -> 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 :: (SetMember Process (Process q) r, Observable o, HasCallStack) => SchedulerProxy q -> 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 :: (SetMember Process (Process q) r, Member (State (Observers o)) r, Observable o) => SomeObserver o -> Eff r ()
-- | Delete an Observer from the Observers managed by
-- manageObservers.
removeObserver :: (SetMember Process (Process q) 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 q. (Observable o, SetMember Process (Process q) r, Member (State (Observers o)) r) => SchedulerProxy q -> Observation o -> Eff r ()
-- | An Observer that schedules the observations to an effectful
-- callback.
data CallbackObserver o
-- | Start a new process for an Observer that schedules all
-- observations to an effectful callback.
spawnCallbackObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs String) q) => SchedulerProxy q -> (Server o -> Observation o -> Eff (Process q : q) Bool) -> Eff r (Server (CallbackObserver o))
instance GHC.Show.Show (Control.Eff.Concurrent.Api.Observer.SomeObserver o)
instance GHC.Show.Show (Control.Eff.Concurrent.Api.Observer.Observation o) => GHC.Show.Show (Control.Eff.Concurrent.Api.Api (Control.Eff.Concurrent.Api.Observer.CallbackObserver o) r)
instance Control.Eff.Concurrent.Api.Observer.Observable o => Control.Eff.Concurrent.Api.Observer.Observer (Control.Eff.Concurrent.Api.Observer.CallbackObserver o) o
instance GHC.Classes.Ord (Control.Eff.Concurrent.Api.Observer.SomeObserver o)
instance GHC.Classes.Eq (Control.Eff.Concurrent.Api.Observer.SomeObserver o)