- interpretAsHandler :: (Event a -> Event b) -> AddHandler a -> AddHandler b
- compile :: MomentIO () -> IO EventNetwork
- data MomentIO a
- module Control.Event.Handler
- fromAddHandler :: AddHandler a -> MomentIO (Event a)
- fromChanges :: a -> AddHandler a -> MomentIO (Behavior a)
- fromPoll :: IO a -> MomentIO (Behavior a)
- reactimate :: Event (IO ()) -> MomentIO ()
- data Future a
- reactimate' :: Event (Future (IO ())) -> MomentIO ()
- changes :: Behavior a -> MomentIO (Event (Future a))
- imposeChanges :: Behavior a -> Event () -> Behavior a
- execute :: Event (MomentIO a) -> MomentIO (Event a)
- liftIOLater :: IO () -> MomentIO ()
- module Control.Monad.IO.Class
- newEvent :: MomentIO (Event a, Handler a)
- mapEventIO :: (a -> IO b) -> Event a -> MomentIO (Event b)
- newBehavior :: a -> MomentIO (Behavior a, Handler a)
- data EventNetwork
- actuate :: EventNetwork -> IO ()
- pause :: EventNetwork -> IO ()
- interpretFrameworks :: (Event a -> Event b) -> [a] -> IO [[b]]
- showNetwork :: EventNetwork -> IO String
Connect to the outside world by building
and running them.
Simple way to write a single event handler with functional reactive programming.
The module presented here allows you to
- obtain input events from external sources and to
- perform output in reaction to events.
In contrast, the functions from Reactive.Banana.Combinators allow you to express the output events in terms of the input events. This expression is called an event graph.
An event network is an event graph together with inputs and outputs.
To build an event network,
describe the inputs, outputs and event graph in the
and use the
compile function to obtain an event network from that.
To activate an event network, use the
The network will register its input event handlers and start
A typical setup looks like this:
main = do -- initialize your GUI framework window <- newWindow ... -- describe the event network let networkDescription :: MomentIO () networkDescription = do -- input: obtain Event from functions that register event handlers emouse <- fromAddHandler $ registerMouseEvent window ekeyboard <- fromAddHandler $ registerKeyEvent window -- input: obtain Behavior from changes btext <- fromChanges "" $ registerTextChange editBox -- input: obtain Behavior from mutable data by polling bdie <- fromPoll $ randomRIO (1,6) -- express event graph behavior1 <- accumB ... let ... event15 = union event13 event14 -- output: animate some event occurrences reactimate $ fmap print event15 reactimate $ fmap drawCircle eventCircle -- compile network description into a network network <- compile networkDescription -- register handlers and start producing outputs actuate network
Building event networks with input/output
MomentIO monad is used to add inputs and outputs
to an event network.
Behavior by frequently polling mutable data, like the current time.
Behavior will be updated on whenever the event
network processes an input event.
This function is occasionally useful, but
the recommended way to obtain
Behaviors is by using
Ideally, the argument IO action just polls a mutable variable, it should not perform expensive computations. Neither should its side effects affect the event network significantly.
IO action whenever the event occurs.
Note: If two events occur very close to each other,
there is no guarantee that the
reactimates for one
event will have finished before the ones for the next event start executing.
This does not affect the values of events and behaviors,
it only means that the
reactimate for different events may interleave.
Fortunately, this is a very rare occurrence, and only happens if
- you call an event handler from inside
- or you use concurrency.
In these cases, the
reactimates follow the control flow
of your event-based framework.
Note: An event network essentially behaves like a single,
huge callback function. The
IO action are not run in a separate thread.
The callback function will throw an exception if one of your
does so as well.
Your event-based framework will have to handle this situation.
Future monad is just a helper type for the
A value of type
Future a is only available in the context
reactimate but not during event processing.
observe when a
Strictly speaking, a
Behavior denotes a value that
varies continuously in time,
so there is no well-defined event which indicates when the behavior changes.
Still, for reasons of efficiency, the library provides a way to observe
changes when the behavior is a step function, for instance as
stepper. There are no formal guarantees,
but the idea is that
changes =<< stepper x e = return e
Note: The values of the event will not become available
until event processing is complete.
It can be used only in the context of
plainChanges :: Behavior a -> MomentIO (Event a) plainChanges b = do (e, handle) <- newEvent eb <- changes b reactimate' $ (fmap handle) <$> eb return e
However, this approach is not recommended, because the result
will occur slightly later than the event returned by
In fact, there is no guarantee whatsoever about what slightly means
in this context. Still, it is useful in some cases.
Dynamically add input and output to an existing event network.
Note: You can even do
IO actions here,
which is useful if you want to register additional event handlers
However, there is no
guarantee about the order in which the actions are executed.
If the result
Event of this function is garbage collected,
it may also happen that the actions are not executed at all.
If you want a reliable way to turn events into
This section collects a few convience functions built from the core functions.
Build a new
Event that contains the result
of an IO computation.
The input and result events will not be simultaneous anymore,
the latter will occur later than the former.
mapEventIO f e1 = do (e2, handler) <- newEvent reactimate $ (\a -> f a >>= handler) <$> e1 return e2
Running event networks
Data type that represents a compiled event network. It may be paused or already running.
Actuate an event network. The inputs will register their event handlers, so that the networks starts to produce outputs in response to input events.
Pause an event network. Immediately stop producing output. (In a future version, it will also unregister all event handlers for inputs.) Hence, the network stops responding to input events, but it's state will be preserved.
You can resume the network with
Note: You can stop a network even while it is processing events,
i.e. you can use
pause as an argument to
The network will not stop immediately though, only after
the current event has been processed completely.
Interpret by using a framework internally. Only useful for testing library internals.