úÎr o’%      !"#$ Safe-Infered qReal-time Actions. This monad is used to build sequential processors that can be turned into stream processors. } An RTA emits zero or more events in response to each input event, and has a state that persists from one event to the next. + In particular, state changes made after a pauseE will be visible to the next event regardless of the relative times. RA conditional stream: events matching the predicate will be passed to the stream. "Real Time Stream Processor (RTSP) gAn EventStream cannot exist independently of some event that caused it to start. Hence the only way to + create an EventStream is through an RTSP.  mempty- is the event sink: it never emits an event.  mappend: runs its arguments in parallel and merges their outputs.  id= is the null operation: events are passed through unchanged.  (.)d is sequential composition: events emitted by the second argument are passed to the first argument. BA real-time event stream cannot be described without reference to unknown future inputs. Hence  EventStream embodies two possible futures:  An Event c8 will be emitted at some time in the future, with a new   EventStream, representing the future after that event.  An incoming Event b will arrive before the next Event c is emitted,  creating a new  EventStream. representing the response to that event. The  old Event c# may or may not be part of the new  EventStream. %There are also two degenerate cases: 4 Wait: no event is scheduled to be emitted, and the  EventStream $ just waits for an incoming event. G Finish: no event will ever be emitted, regardless of incoming events. D This is explicitly distinguished so that complex RTSP expressions  can be GC'(d if they can be proven to be finished. JEvent streams are like the Mirror of Galadriel, for they show things that Lwere, things that are, and things that yet may be. But which it is that he *sees, even the wisest cannot always tell. FSeeing is both good and perilous. An event stream may be modified by Nnew events, but exceptions or inconsistent results will occur if the incoming ,events are not in increasing order of time. Real time events. GTrue if the first event occurs strictly before the second. This makes Event" a poset (partially ordered set). < Infix priority 4 (the same as other comparison operators). bPeek at the events that will be emitted by this EventStream if no incoming event interrupts them. WTrue if the first argument is scheduled to emit an event before the second. This makes  EventStream a poset - (partially ordered set). Infix priority 4. .All the possible futures of the event stream. [True if the event stream is guaranteed not to emit any future events, regardless of input. DMerge the outputs of two event streams. Input events are delivered  to both streams. bGiven a new input event to an existing event stream, this returns the modified event stream. When  esProcess l is called on the result the Event argument to the second call must not occur before the first (they can be # simultaneous). More formally, if  - esOut = esProcess (esProcess esIn ev1) ev2 then  not (ev2   ev1)%. This precondition is not checked. /An event stream that never generates anything. >Execute an RTSP against a list of events. Useful for testing. sExecute an RTSP in the IO monad. The function returns immediately with an action for pushing events into the RTSP. 2A pure function converted into a stream processor uWhen a new input event is delivered to an RTSP it causes any future output events to be dropped in favour of the new  events.  accumulateY instead keeps the events from previous inputs interleaved with the new ones. If you use 9 this unnecessarily then you will get duplicated events.  If there are ng output events due to be emitted before an input event then this will require O(n) time for the input. wRepeat each input event after the specified delays until a new event arrives, at which point the sequence begins again v with the new event value. The list of delays must not be negative and must be in ascending order. All the delays are  relative to the first event. OBe careful when using list comprehensions to create the argument. A list like   [1..5] :: NominalDiffTime dwill count up in picoseconds rather than seconds, which is probably not what is wanted. Instead use + map fromInteger [1..5] :: NominalDiffTime DDelay input events by the specified time, but given an event stream {ev1, ev2, ev3...}, if ev2 arrives before - ev1 has been emitted then ev1 will be lost. *Delay input events by the specified time. 5Unfortunately this requires O(n) time when there are n$ events queued up due to the use of  accumulate. DConditional stream execution: only certain events will be accepted. 3Send each event to all the streams that accept it. =Send each event to the first stream that accepts it, if any. fSend each event to the conditional stream if it accepts it, otherwise send it to the second argument. ifThenElse (p, rThen) rElse is equivalent to  B streamFilter (p, rThen) `mappend` streamFilter (not . p, rElse) However  ifThenElse only evaluates p once for each input event. >Get the current time. This is the event time plus any pauses. Get the current state. Put the current state. 'Apply a function to the current state. !Emit a value as an event. "zPause before the next step. This does not actually delay processing; it merely increments the time of any emitted events. #9Execute an RTA as part of a real time stream processor. |When a new event arrives any pending output events will be lost. However any state changes are immediately visible to the " next event, even if they occured "after"0 the lost events. For instance, consider this:   execRTA 1 $ \_ -> do  n <- get  pause 10  emit n  put (n+1)  return True If this receives events at  t=[0,1,3,20] then it will emit [Event 13 3, Event 30 4]*. The events that would have been emitted  at t=[10,11]d have been lost, but the state change still occured immediately, regardless of the output schedule. $Like execRTA-, except that output events are accumulated. / The processor to execute. JThe events must be finite and in chronological order. This is unchecked. tThe output of the RTSP is a series of action events that will be executed in a separate thread sequentially at the P times given. The actions may, of course, fork their own threads as necessary. execRTSP uses % , so it cannot be called within unsafePerformIO.  !"#8The initial state. State persists between input events. DA function from the input value to an action. If the action returns True then subsequent input events * will run the action again. If it returns FalseA then the RTSP finishes and will not respond to further events. $&'()*+,-./%  !"#$%    !"#$*  !"#$&'()*+,-./0      !"#$%&'()*+,-./012 Dflow-0.0.1 Control.RTSPRTACondRTSPrunRTSP EventStreamEvent eventTime eventValueisBeforeesPeek emitsBefore esFutures esFinishedesMerge esProcess nullStream simulateRTSPexecRTSPstream accumulate repeatEventdelay0delay streamFiltercondcond1 ifThenElsenowgetputmodifyemitpauseexecRTA accumulateRTAbase GHC.Conc.Sync atomically $fMonadRTA $fFunctorRTA$fCategoryRTSP$fCategoryEventStream $fFunctorRTSP$fFunctorEventStream$fMonoidEventStream $fMonoidRTSP $fShowRTSP$fFunctorEvent