!V?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~        !!!!!!!"""###$$$$$$%%%%%%%%%%%%%%&&*Safe4%grhine Values in ScheduleT diff m/ are delayed computations with side effects in mM. Delays can occur between any two side effects, with lengths specified by a diffL value. These delays don't have any semantics, it can be given to them with k.hrhine6A functor implementing a syntactical "waiting" action.diff! represents the duration to wait.a is the encapsulated value.jrhine2The side effect that waits for a specified amount.krhineSupply a semantic meaning to h. For every occurrence of  Wait diff in the ScheduleT diff m a6 value, a waiting action is executed, depending on diff.lrhineRun a g value in a ,, interpreting the times as milliseconds.mrhineRuns two values in g concurrently and returns the first one that yields a value (defaulting to the first argument), and a continuation for the other value.nrhineFRuns both schedules concurrently and returns their results at the end.ghijklmnhigjklmn'Safe'rhine Commute a  layer past an X layer.rhineCommute the effects of the  and the X monad.(Safe(rhine Commute one  layer past a  layer.)Safe*4prhineDIn a composite running clock, duplicate the tick of one subclock.pqNone=?HMV-rrhineAny  can be wrapped to form a u.urhineA time domain is an affine space representing a notion of time, such as real time, simulated time, steps, or a completely different notion.crstuvwrstuvwcNone"#=>?@AHPSVX]| rhineLift a clock type into .rhine+Lift a clock type into a monad transformer.rhine-Applying a monad morphism yields a new clock.rhineInstead of a mere function as morphism of time domains, we can transform one time domain into the other with a monadic stream function.rhineThe clock before the rescalingrhinekThe rescaling stream function, and rescaled initial time, depending on the initial time before rescalingrhineInstead of a mere function as morphism of time domains, we can transform one time domain into the other with an effectful morphism.rhineThe clock before the rescalingrhine4Computing the new time effectfully from the old timerhine7Applying a morphism of time domains yields a new clock.rhineLike `, but allows for an initialisation of the rescaling morphism, together with the initial time.rhine6An effectful, stateful morphism of time domains is an LU that uses side effects to rescale a point in one time domain into another one.rhineAn effectful morphism of time domains is a Kleisli arrow. It can use a side effect to rescale a point in one time domain into another one.rhine3A pure morphism of time domains is just a function.rhineAn annotated, rich time stamp.rhineTime passed since the last tickrhine1Time passed since the initialisation of the clockrhine%The absolute time of the current tickrhine&The tag annotation of the current tickrhine}Since we want to leverage Haskell's type system to annotate signal networks by their clocks, each clock must be an own type, cl. Different values of the same clock type should tick at the same speed, and only differ in implementation details. Often, clocks are singletons.rhine@The time domain, i.e. type of the time stamps the clock creates.rhineAdditional information that the clock may output at each tick, e.g. if a realtime promise was met, if an event occurred, if one of its subclocks (if any) ticked.rhineThe method that produces to a clock value a running clock, i.e. an effectful stream of tagged time stamps together with an initialisation time.rhineWhen initialising a clock, the initial time is measured (typically by means of a side effect), and a running clock is returned.rhinesA clock creates a stream of time stamps and additional information, possibly together with side effects in a monad mH that cause the environment to wait until the specified time is reached.rhine$A utility that changes the tag of a .rhineoConvert an effectful morphism of time domains into a stateful one with initialisation. Think of its type as 4RescalingM m cl time -> RescalingSInit m cl time tag%, although this type is ambiguous.rhineA  is trivially a .rhineA  is trivially a .rhineA  is trivially a .rhine,Lift a clock value into a monad transformer.rhineLift a clock value into .rhine>The clock value, containing e.g. settings or device parametersrhine/The stream of time stamps, and the initial timeq  !",-./0123456789:;<=>?@ABCDEFGHIJKLcrstuvwq  !",-./0123456789:;<=>?@ABCDEFGHIJKLcrstuvwNone"#&'=>?@AHSVXrhineGAn inclusion of a clock into a tree of parallel compositions of clocks.rhine`A tree representing possible last times to which the constituents of a clock may have ticked.rhineCThe clock that represents the rate at which data leaves the system.rhineCThe clock that represents the rate at which data enters the system.rhineAbbrevation synonym.rhineuTwo clocks can be combined with a schedule as a clock for an asynchronous parallel composition of signal networks.rhineAbbrevation synonym.rhinewTwo clocks can be combined with a schedule as a clock for an asynchronous sequential composition of signal networks.rhineUA schedule implements a combination of two clocks. It outputs a time stamp and an A value, which specifies which of the two subclocks has ticked.rhine'Lift a schedule along a monad morphism.rhine&Swaps the clocks for a given schedule.rhine^If a schedule works for two clocks, a rescaling of the clocks also applies to the schedule.rhineAs , with a stateful rescalingrhineLifts a schedule into the H transformer, supplying the same environment to its scheduled clocks.rhinecl1 is a subclock of SequentialClock m cl1 cl2, therefore it is always possible to schedule these two clocks deterministically. The left subclock of the combined clock always ticks instantly after cl1.rhineAs h, but for the right subclock. The right subclock of the combined clock always ticks instantly before cl2.rhineLike c, but for parallel clocks. The left subclock of the combined clock always ticks instantly after cl1.rhineLike H, but the left subclock of the combined clock always ticks instantly before cl1.rhineLike h, but for the right subclock. The right subclock of the combined clock always ticks instantly before cl2.rhineLike I, but the right subclock of the combined clock always ticks instantly after cl2.rhinehGenerates a tag for the composite clock from a tag of a leaf clock, given a parallel clock inclusion.%% None"#>HVarhineTwo clocks in the gd monad transformer can always be canonically scheduled. Indeed, this is the purpose for which g was defined. None>HVArhineRuns two clocks in separate GHC threads and collects the results in the foreground thread. Caution: The data processing will still happen in the same thread (since data processing and scheduling are separated concerns).rhineAs  , but in the  WriterT w IOs monad. Both background threads share a joint variable with the foreground to which the writer effect writes.rhineSchedule in the  ExceptT e IO9 monad. Whenever one clock encounters an exception in X3, this exception is thrown in the other clock's XK layer as well, and in the schedule's (i.e. in the main clock's) thread.rhineAs ), with a single possible exception value. None"#HSVXrhine)A type synonym to allow for abbreviation.rhine%A stateful buffer from which one may  a value, or to which one may # a value, depending on the clocks. :s can be clock-polymorphic, or specific to certain clocks.m: Monad in which the  may have side effectscla+: The clock at which data enters the bufferclb+: The clock at which data leaves the buffera: The input typeb: The output typerhineStore one input value of type a5 at a given time stamp, and return a continuation.rhine"Retrieve one output value of type b. at a given time stamp, and a continuation.rhineHoist a  along a monad morphism.w  !",-./0123456789:;<=>?@ABCDEFGHIJKLcrstuvw None"#FrhineAn asynchronous, effectful Mealy machine description. (Input and output do not happen simultaneously.) It can be used to create s.rhineBGiven the previous state and an input value, return the new state.rhineAGiven the previous state, return an output value and a new state.rhineA resampling buffer that is unaware of the time information of the clock, and thus clock-polymorphic. It is built from an asynchronous Mealy machine description. Whenever  is called on "timelessResamplingBuffer machine s, the method  is called on machine with state s0, discarding the time stamp. Analogously for .rhine6A resampling buffer that only accepts and emits units.rhineThe initial state None"#1rhineZGiven a monadic stream function that accepts a varying number of inputs (a list), a @ can be formed that collects all input in a timestamped list.rhineThe monadic stream function that consumes a single time stamp for the moment when an output value is required, and a list of timestamped inputs, and outputs a single value. The list will contain the newest element in the head.None"#rhineDAn unbounded LIFO buffer. If the buffer is empty, it will return .rhineA bounded LIFO buffer that forgets the oldest values when the size is above a given threshold. If the buffer is empty, it will return .rhine<An unbounded LIFO buffer that also returns its current size.None"#rhine\Always keeps the last input value, or in case of no input an initialisation value. If cl2A approximates continuity, this behaves like a zero-order hold.None"#rhineDAn unbounded FIFO buffer. If the buffer is empty, it will return .rhineA bounded FIFO buffer that forgets the oldest values when the size is above a given threshold. If the buffer is empty, it will return .rhine<An unbounded FIFO buffer that also returns its current size.None"#SrhineiCollects all input in a list, with the newest element at the head, which is returned and emptied upon .rhineReimplementation of g with sequences, which gives a performance benefit if the sequence needs to be reversed or searched.rhinej collects all input values lazily in a list and processes it when output is required. Semantically, "pureBuffer f == collect >>-^ arr f , but  is slightly more efficient.rhinegA buffer collecting all incoming values with a folding function. It is strict, i.e. the state value b is calculated on every .rhineThe folding functionrhineThe initial valueNone&'8>HVWrhine"Extract a clock proxy from a type.rhineGClocks should be able to automatically generate a proxy for themselves.rhineBWitnesses the structure of a clock type, in particular whether s or s are involved.rhineLReturn the incoming tag, assuming that the incoming clock is ticked, and  otherwise.rhineLReturn the incoming tag, assuming that the outgoing clock is ticked, and  otherwise. None"#_rhineMGiven a clock value and an initial time, generate a stream of time stamps.None "#=?@AHPV٩rhine/A clock that selects certain subevents of type a", from the tag of a main clock.If two `s would tick on the same type of subevents, but should not have the same type, one should newtype the subevent.rhineThe main clock | Return ^ if no tick of the subclock is required, or 'Just a' if the subclock should tick, with tag a.rhine[A universal schedule for two subclocks of the same main clock. The main clock must be a  (e.g. a singleton). rhine7A universal schedule for a subclock and its main clock. rhineHelper function that runs an L with $ output until it returns a value.    None=?@AHV rhine]A clock that ticks for every line entered on the console, outputting the entered line as its .  None@AHVrhineA clock that ticks without waiting. All time passed between ticks amounts to computation time, side effects, time measurement and framework overhead.None .=?@AHVrhineA rescaled version of  with u .rhineWA side-effect free clock for audio synthesis and analysis. The sample rate is given by rate (of type ). Since this clock does not wait for the completion of buffers, the producer or the consumer of the signal has the obligation to synchronise the signal with the system clock, if realtime is desired. Otherwise, the clock is also suitable e.g. for batch processing of audio files.rhine]A clock for audio analysis and synthesis. It internally processes samples in buffers of size  bufferSizeJ, (the programmer does not have to worry about this), at a sample rate of rate (of type ). Both these parameters are in the type signature, so it is not possible to compose signals with different buffer sizes or sample rates.After processing a buffer, the clock will wait the remaining time until the next buffer must be processed, using system UTC time. The tag of the clock specifies whether the attempt to finish the last buffer in real time was successful. A value of  represents success, a value of  Just double represents a lag of double seconds.rhine3Rates at which audio signals are typically sampled.rhine Converts an ! to its corresponding rate as an .rhineA rescaled version of  with u  , using  to rescale.  None&'-.=>?@AHUV'rhineeA clock whose tick lengths cycle through a (nonempty) list of type-level natural numbers. E.g. Periodic '[1, 2]& ticks at times 1, 3, 4, 5, 7, 8, etc.&The waiting side effect is formal, in g. You can use e.g. l to produce an actual delay.rhine8Repeatedly outputs the values of a given list, in order.'('(NoneHSVX-rhine(Compatibility to U.S. american spelling..rhineA (side-effectful) behaviour function is a time-aware synchronous stream function that doesn't depend on a particular clock. time denotes the u./rhine(Compatibility to U.S. american spelling.0rhineeA (side-effectful) behaviour is a time-aware stream that doesn't depend on a particular clock. time denotes the u.1rhineA clocked signal is a 2> with no input required. It produces its output on its own.2rhineA (synchronous, clocked) monadic stream function with the additional side effect of being time-aware, that is, reading the current  of the clock cl.3rhineHoist a 2 along a monad morphism.4rhineHoist a 2& and its clock along a monad morphism.5rhineLift a 2 into a monad transformer.6rhineLift a 2( and its clock into a monad transformer.7rhine=A monadic stream function without dependency on time is a 2 for any clock.8rhine+Utility to lift Kleisli arrows directly to 2s.9rhineVersion without input.:rhineCall a 2" every time the input is 'Just a'.[Caution: This will not change the time differences since the last tick. For example, while  integrate 1 is approximately the same as timeInfoOf sinceInit, mapMaybe $ integrate 1 is very different from mapMaybe $ timeInfoOf sinceInit/. The former only integrates when the input is Just 1J, whereas the latter always returns the correct time since initialisation.  !",-./0123456789:;<=>?@ABCDEFGHIJKLcrstuvw-./0123456789:-./0123456789:  !",-./0123456789:;<=>?@ABCDEFGHIJKLcrstuvwNone &'>HSVX!];rhineAn ;" is a side-effectful asynchronous signal networkd, where input, data processing (including side effects) and output need not happen at the same time.The type parameters are:m-: The monad in which side effects take place.clp: The clock of the whole signal network. It may be sequentially or parallely composed from other clocks.a,: The input type. Input arrives at the rate In cl.b.: The output type. Output arrives at the rate Out cl.<rhineRA synchronous monadic stream function is the basic building block. For such an ;H, data enters and leaves the system at the same rate as it is processed.=rhineTwo ;6s may be sequentially composed if there is a matching  between them.>rhineTwo ;@s with the same input and output data may be parallely composed.;>=<;>=<None"#HV)@rhineAn L{ can be given arbitrary other arguments that cause it to tick without doing anything and replicating the last output.Arhine Upsample a 2# to a parallel clock. The given 2 is only called when clRF ticks, otherwise the last output is replicated (with the given b as initialisation).Brhine Upsample a 2# to a parallel clock. The given 2 is only called when clLF ticks, otherwise the last output is replicated (with the given b as initialisation).@AB@ABNoneHPSVX0lCrhine Commute two # transformer layers past each otherDrhineCreate ("wrap") a < layer in the monad stack of a behaviour. Each tick, the I side effect is performed by passing the original behaviour the extra r input.ErhineRemove ("run") a O layer from the monad stack by making it an explicit input to the behaviour.Frhine Remove a 6 layer by passing the readonly environment explicitly.CDEFCDEFNoneHSVX:Grhine>Generates random values, updating the generator on every step.Hrhine<Updates the generator every step but discards the generator.IrhineZUpdates the generator every step but discards the value, only outputting the generator.JrhineFEvaluates the random computation by using the global random generator.KrhineXEvaluates the random computation by using the global random generator on the first tick.Lrhine%Produce a random value at every tick.MrhineGProduce a random value at every tick, within a range given per tick.NrhineCProduce a random value at every tick, within a range given once.GrhineThe initial random seed )*+GHIJKLMN GHIJKLMN)*+NoneHSVXSOrhine(Compatibility to U.S. american spelling.PrhineA clock polymorphic QN, or equivalently an exception-throwing behaviour. Any clock with time domain time may occur.QrhineCA synchronous exception-throwing signal function. It is based on a newtype from Dunai, , to exhibit a monad interface in the exception type.  then corresponds to throwing an exception, and `(>>=)` is exception handling. (For more information, see the documentation of .)m>: The monad that the signal function may take side effects incl.: The clock on which the signal function ticksa: The input typeb: The output typee,: The type of exceptions that can be thrownRrhine)Immediately throw the incoming exception.Srhine&Immediately throw the given exception.TrhineDo not throw an exception.Urhine#Throw the given exception when the  turns true.Vrhine Variant of U*, where the exception can vary every tick.WrhineThrow the exception e$ whenever the function evaluates to .Xrhine Variant of W? for Kleisli arrows. | Throws the exception when the input is .YrhineWhen the input is Just e, throw the exception e.Zrhine$Leave the monad context, to use the Q as an .[rhine0Enter the monad context in the exception for 2 s in the X monad. The 2. will be run until it encounters an exception.\rhinecWithin the same tick, perform a monadic action, and immediately throw the value as an exception.]rhine A variant of \ without input.^rhineUAdvances a single tick with the given Kleisli arrow, and then throws an exception.%#$%&'(MNOPQRSTUVXWdefOPQRSTUVWXYZ[\]^OPQRSTUVWXYZ[\]^#$(&'%None "#>HSVX !_rhine(Read the environment variable, i.e. the .`rhine*Utility to apply functions to the current , such as record selectors: ` printAbsoluteTime :: ClSF IO cl () () printAbsoluteTime = timeInfoOf absolute >>> arrMCl print arhine<Continuously return the time difference since the last tick.brhineCContinuously return the time difference since clock initialisation.crhine&Continuously return the absolute time.drhine0Continuously return the tag of the current tick.erhine%Calculate the time passed since this 2- was instantiated. This is _not_ the same as b5, which measures the time since clock initialisation.3For example, the following gives a sawtooth signal: Nsawtooth = safely $ do try $ sinceStart >>> proc time -> do throwOn () - time* 1 returnA -< time safe sawtooth If you replace e by b^, it will usually hang after one second, since it doesn't reset after restarting the sawtooth.frhine Alias for *+k (sequential composition) with higher operator precedence, designed to work with the other operators, e.g.: ;clsf1 >-> clsf2 @@ clA ||@ sched @|| clsf3 >-> clsf4 @@ clB&The type signature specialises e.g. to C(>->) :: Monad m => ClSF m cl a b -> ClSF m cl b c -> ClSF m cl a cgrhine Alias for *,.hrhineAOutput a constant value. Specialises e.g. to this type signature: %arr_ :: Monad m => b -> ClSF m cl a birhine)The identity synchronous stream function.jrhineThe output of integralFrom v0F is the numerical Euler integral of the input, with initial offset v0.krhine,Euler integration, with zero initial offset.lrhineThe output of derivativeFrom v0r is the numerical derivative of the input, with a Newton difference quotient. The input is initialised with v0.mrhine4Numerical derivative with input initialised to zero.nrhineLike la, but uses three samples to compute the derivative. Consequently, it is delayed by one sample.orhineLike n2, but with the initial position initialised to a.prhineZA weighted moving average signal function. The output is the average of the first input, weighted by the second input (which is assumed to be always between 0 and 1). The weight is applied to the average of the last tick, so a weight of 1 simply repeats the past value unchanged, whereas a weight of 0 outputs the current value.qrhine{An exponential moving average, or low pass. It will average out, or filter, all features below a given time constant t5. (Equivalently, it filters out frequencies above 1 / (2 * pi * t).)rrhine-An average, or low pass, initialised to zero.srhineA linearised version of q. It is more efficient, but only accurate if the supplied time scale is much bigger than the average time difference between two ticks.trhineLinearised version of r.urhine Alias for r.vrhineFilters out frequencies below 1 / (2 * pi * t).wrhine#Filters out frequencies other than 1 / (2 * pi * t).xrhineFilters out the frequency 1 / (2 * pi * t).yrhineCRemembers and indefinitely outputs ("holds") the first input value.zrhinedRemembers all input values that arrived within a given time window. New values are appended left.{rhineJDelay a signal by certain time span, initialising with the first input.|rhineaThrows an exception after the specified time difference, outputting the time passed since the | was instantiated.}rhineLike }/, but doesn't output the remaining time at all.~rhineLike |3, but divides the remaining time by the total time.rhineRemembers the last 8 value, defaulting to the given initialisation value. nrhineThe initial positionprhineThe initial positionqrhineThe initial positionrhine.The time scale on which the signal is averagedrrhine.The time scale on which the signal is averagedsrhineThe initial positionrhine.The time scale on which the signal is averagedtrhine.The time scale on which the signal is averagedvrhineThe time constant twrhineThe time constant txrhineThe time constant tzrhineThe size of the time window{rhine!The time span to delay the signal!_`abcdefghijklmnopqrstuvwxyz{|}~!_`abcdefghijklmnopqrstuvwxyz{|}~f6g6-Nonem  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVXWcdefrstuvw-./0123456789:CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~NoneSXrhinePostcompose a  with a matching 2.rhine Precompose a  with a matching 2.rhineParallely compose two s.rhineParallely compose two s, duplicating the input.rhineGiven a  where the output type depends on the input type polymorphically, we can produce a timestamped version that simply annotates every input value with the  when it arrived.2144None&'>8rhine2Postcompose a signal network with a pure function.rhine1Precompose a signal network with a pure function.rhineRCompose two signal networks on the same clock in data-parallel. At one tick of cl, both networks are stepped.rhineUCompose two signal networks on different clocks in clock-parallel. At one tick of ParClock m cl1 cl2U, one of the networks is stepped, dependent on which constituent clock has ticked..Note: This is essentially an infix synonym of >rhineUCompose two signal networks on different clocks in clock-parallel. At one tick of ParClock m cl1 cl2U, one of the networks is stepped, dependent on which constituent clock has ticked. None &'.=?@AHUVrhine(A singleton clock that counts the ticks.rhineVA pure (side effect free) clock with fixed step size, i.e. ticking at multiples of ni. The tick rate is in the type signature, which prevents composition of signals at different rates.rhine4Extract the type-level natural number as an integer.rhineTwo 5 clocks can always be scheduled without side effects.!None .@AHUVrhineA clock ticking every n# milliseconds, in real time. Since nN is in the type signature, it is ensured that when composing two signals on a - clock, they will be driven at the same rate.The tag of this clock is , where % represents successful realtime, and  a lag.rhineThis implementation measures the time after each tick, and waits for the remaining time until the next tick. If the next tick should already have occurred, the tag is set to *, representing a failed real time attempt.rhineTwo 2 clocks can always be scheduled deterministically."None"#>HVrhineQA simple linear interpolation based on the last calculated position and velocity.rhine7sinc-Interpolation, or Whittaker-Shannon-Interpolation.FThe incoming signal is strictly bandlimited by the frequency at which cl1Y ticks. Each incoming value is hulled in a sinc function, these are added and sampled at cl2's ticks. In order not to produce a space leak, the buffer only remembers the past values within a given window, which should be chosen much larger than the average time between cl1 's ticks.rhine7Interpolates the signal with Hermite splines, using o.oCaution: In order to calculate the derivatives of the incoming signal, it has to be delayed by two ticks of cl1R. In a non-realtime situation, a higher quality is achieved if the ticks of cl2 are delayed by two ticks of cl1.rhine/The initial velocity (derivative of the signal)rhineThe initial positionrhine^The size of the interpolation window (for how long in the past to remember incoming values)#None"#&'>P"rhinetRun a clocked signal function as a monadic stream function, accepting the timestamps and tags as explicit inputs.rhine2Run a signal network as a monadic stream function.Depending on the incoming clock, input data may need to be provided, and depending on the outgoing clock, output data may be generated. There are thus possible invalid inputs, which  does not gracefully handle.rhine=Translate a resampling buffer into a monadic stream function.The input decides whether the buffer is to accept input or has to produce output. (In the latter case, only time information is provided.)None .=>?@AHSVX rhineA clock that ticks whenever an event is emitted. It is not yet bound to a specific channel, since ideally, the correct channel is created automatically by Q. If you want to create the channel manually and bind the clock to it, use .rhine:A monad transformer in which events can be emitted onto a .rhine Escape the i layer by explicitly providing a channel over which events are sent. Often this is not needed, and  can be used instead.rhineuCreate a channel across which events can be communicated, and subsequently execute all event effects on this channel.)Ideally, this action is run _outside_ of flow, e.g. runEventChanT $ flow myRhine+. This way, exactly one channel is created.Caution: Don't use this with BF, since it would create a new channel every tick. Instead, create one chan :: Chan c , e.g. with , and then use .rhineRemove ("run") an \ layer from the monad stack by passing it explicitly the channel over which events are sent.-This is usually only needed if you can't use , to create the channel. Typically, create a chan :: Chan c1 in your main program before the main loop (e.g. flowU) would be run, then, by using this function, pass the channel to every behaviour or 2* that wants to emit events, and, by using /, to every clock that should tick on the event.rhine'Emit a single event. This causes every ' on the same monad to tick immediately.=Be cautious when emitting events from a signal clocked by an q. Nothing prevents you from emitting more events than are handled, causing the event buffer to grow indefinitely.rhineEmit an event on every tick.rhine*Emit an event whenever the input value is  Just event.rhineLike 8, but completely evaluates the event before emitting it.rhineLike 8, but completely evaluates the event before emitting it.rhineLike 8, but completely evaluates the event before emitting it.rhinesCreate an event clock that is bound to a specific event channel. This is usually only useful if you can't apply  to the main loop (see ).rhineGiven two clocks with an  layer directly atop the X monad, you can schedule them using concurrent GHC threads, and share the event channel.Typical use cases:=Different subevent selection clocks (implemented i.e. with .)) on top of the same main event source.5An event clock and other event-unaware clocks in the ! monad, which are lifted using .$None"#HVrhineA  consists of a ;( together with a clock of matching type cl._It is a reactive program, possibly with open inputs and outputs. If the input and output types a and b are both '()', that is, the Y is "closed", then it is a standalone reactive program that can be run with the function flow.fOtherwise, one can start the clock and the signal network jointly as a monadic stream function, using .rhine[Start the clock and the signal network, effectively hiding the clock type from the outside.%None>EHVX# rhinewA purely syntactical convenience construction allowing for ternary syntax for parallel composition, described below.rhinezA purely syntactical convenience construction enabling quadruple syntax for sequential composition, as described below.rhineeA point at which sequential asynchronous composition ("resampling") of signal networks can happen.rhineCreate a synchronous z by combining a clocked signal function with a matching clock. Synchronicity is ensured by requiring that data enters (In cl) and leaves (Out cl-) the system at the same as it is processed (cl).rhineSyntactic sugar for .rhineSyntactic sugar for .rhineJThe combinators for sequential composition allow for the following syntax: brh1 :: Rhine m cl1 a b rh1 = ... rh2 :: Rhine m cl2 c d rh2 = ... rb :: ResamplingBuffer m (Out cl1) (In cl2) b c rb = ... sched :: Schedule m cl1 cl2 sched = ... rh :: Rhine m (SequentialClock m cl1 cl2) a d rh = rh1 >-- rb -@- sched --> rh2 rhineSyntactic sugar for .rhineHThe combinators for parallel composition allow for the following syntax: !rh1 :: Rhine m clL a b rh1 = ... rh2 :: Rhine m clR a c rh2 = ... sched :: Schedule m clL clR sched = ... rh :: Rhine m (ParallelClock clL clR) a (Either b c) rh = rh1 ++@ sched @++ rh2 rhineFurther syntactic sugar for .rhineHThe combinators for parallel composition allow for the following syntax: rh1 :: Rhine m clL a b rh1 = ... rh2 :: Rhine m clR a b rh2 = ... sched :: Schedule m clL clR sched = ... rh :: Rhine m (ParallelClock clL clR) a b rh = rh1 ||@ sched @|| rh2 58214343&None"#&'/rhineTakes a closed \ (with trivial input and output), and runs it indefinitely. This is typically the main loop.cAll input has to be created, and all output has to be consumed by means of side effects in a monad m.Basic usage (synchronous case): Dsensor :: ClSF MyMonad MyClock () a sensor = constMCl produceData processing :: ClSF MyMonad MyClock a b processing = ... actuator :: ClSF MyMonad MyClock b () actuator = arrMCl consumeData mainSF :: ClSF MyMonad MyClock () () mainSF = sensor >-> processing >-> actuator main :: MyMonad () main = flow $ mainSF @@ clock rhineRun a synchronous 2C with its clock as a main loop, similar to Yampa's, or Dunai's, H.None0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVXWba`_^]\[ZYcdefpqrstuvw   '(-./0123456789:;<=>CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVXWba`_^]\[ZYcdefpqrstuvw   '(-./0123456789:;<=>CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~/01/02/03/04/05/67/68/9:/0;/0</0=/0>/0?/0@/0A/0B/0C/0D/0E/0F/0F/0G/0H/0I/0J/0K/0L/0M/0N/0O/0P/0P/0Q/*+/*,RSTRSURSVRSWRSXRSYRZ[RZ\RZ]R^_R^`R^aR^bR^cR^dR^eR^fR^gR^hR^iR^jR^kR^lR^mR^nR^oR^pR^qR^rR^sR^tRuvRuwRuxRuyRuzRu{R|}R|~R|R|R|))                   !"#$%&'()*+,-./01223456789::;<=>>?@ABBCCDEFGHIJKLMNOPPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~        !!!!!!!"""###$$$$$$%%%%%%%%%%%%%%&&''(///////RS///9 "rhine-0.7.0-CBWVaZXu8vHFceDVh6vSjPFRP.Rhine.Clock FRP.RhineFRP.Rhine.Clock.Realtime.EventFRP.Rhine.ClSF.ExceptFRP.Rhine.ClSF.RandomFRP.Rhine.TimeDomainControl.Monad.ScheduleFRP.Rhine.ScheduleFRP.Rhine.Schedule.TransFRP.Rhine.Schedule.ConcurrentlyFRP.Rhine.ResamplingBuffer#FRP.Rhine.ResamplingBuffer.TimelessFRP.Rhine.ResamplingBuffer.MSFFRP.Rhine.ResamplingBuffer.LIFO#FRP.Rhine.ResamplingBuffer.KeepLastFRP.Rhine.ResamplingBuffer.FIFO"FRP.Rhine.ResamplingBuffer.CollectFRP.Rhine.Clock.ProxyFRP.Rhine.Clock.UtilFRP.Rhine.Clock.SelectFRP.Rhine.Clock.Realtime.StdinFRP.Rhine.Clock.Realtime.BusyFRP.Rhine.Clock.Realtime.AudioFRP.Rhine.Clock.PeriodicFRP.Rhine.ClSF.Core FRP.Rhine.SNFRP.Rhine.ClSF.UpsampleFRP.Rhine.ClSF.ReaderFRP.Rhine.ClSF.UtilFRP.Rhine.ResamplingBuffer.UtilFRP.Rhine.SN.CombinatorsFRP.Rhine.Clock.FixedStep$FRP.Rhine.Clock.Realtime.Millisecond(FRP.Rhine.ResamplingBuffer.Interpolation#FRP.Rhine.Reactimation.ClockErasureFRP.Rhine.Type"FRP.Rhine.Reactimation.CombinatorsFRP.Rhine.ReactimationFRP.Rhine.ClSF.Except.UtilFRP.Rhine.ClSF.Random.UtilFRP.Rhine.Schedule.UtilControl.Category>>><<<FRP.Rhine.ClSFSelectbase Control.Arrowarrfirstapp|||loopControl.Monad.IO.ClassliftIOMonadIOControl.Concurrent.ChannewChanleftApp^<<<<^>>^^>>returnA&&&***secondArrow runKleisliKleisli zeroArrow ArrowZero<+> ArrowPlus+++rightleft ArrowChoice ArrowApply ArrowMonad ArrowLoop"dunai-0.7.0-CRjTrkch93ICb5cgE9fPfnControl.Monad.Trans.MSF.Exceptsafesafely currentInputexceptS runMSFExceptEmptyControl.Monad.Trans.MSF.Random getRandomsRS_ getRandomsRS getRandomsSData.MonadicStreamFunction.UtilpauseOn traceWhen traceWithtrace repeatedlyunfoldmealyaccumulateWith mappendFrommappendSsumFromsumScountfifonextiPostiPrewithSideEffect_withSideEffect mapMaybeSMStreamMSinkData.MonadicStreamFunction.CoremorphS liftTransS liftBaseS liftBaseMarrMconstM'Data.MonadicStreamFunction.InternalCore reactimateembedfeedbackmorphGSMSFtransformers-0.5.5.0Control.Monad.Trans.ExceptexceptthrowEcatchE withExceptT mapExceptT runExceptT withExcept mapExcept runExceptExceptExceptT0simple-affine-space-0.1.1-KxtqaVGLwEf9QbrI4YdalWData.VectorSpace normalizenormdot negateVector^-^^+^^/*^ zeroVector VectorSpace time-1.8.0.2 Data.Time.Clock.Internal.UTCTimeUTCTimeliftPass liftListen liftCallCC ScheduleTWaitwait runScheduleT runScheduleIOraceasync $fFunctorWaitduplicateSubtick swapEither NumTimeDomainfromNumTimeDomain TimeDomainDiffdiffTime$fTimeDomain()$fTimeDomainInteger$fTimeDomainFloat$fTimeDomainDouble$fTimeDomainUTCTime$fTimeDomainNumTimeDomain$fNumNumTimeDomainIOClock LiftClock HoistClockunhoistedClock monadMorphismRescaledClockSunscaledClockSrescaleSRescaledClockMunscaledClockMrescaleM RescaledClock unscaledClockrescaleRescalingSInit RescalingS RescalingM RescalingTimeInfo sinceLast sinceInitabsolutetagClockTimeTag initClockRunningClockInit RunningClockretagrescaleMToSInitrescaledClockToMrescaledClockMToSrescaledClockToS liftClockioClock$fClockmRescaledClock$fClockmRescaledClockM$fClockmRescaledClockS$fClockm2HoistClockParClockInclusion ParClockInL ParClockInR ParClockReflLastTimeSequentialLastTimeParallelLastTime LeafLastTimeOutInParClock ParallelClock parallelCl1 parallelCl2parallelScheduleSeqClockSequentialClock sequentialCl1 sequentialCl2sequentialScheduleSchedule initSchedule hoistSchedule flipSchedulerescaledSchedulerescaledScheduleSreaderSchedule schedSeq1 schedSeq2 schedPar1 schedPar1' schedPar2 schedPar2'parClockTagInclusion$fClockmSequentialClock$fClockmParallelClockschedule concurrentlyconcurrentlyWriterconcurrentlyExceptconcurrentlyMaybeResBufResamplingBufferputgethoistResamplingBuffer AsyncMealyamPutamGettimelessResamplingBuffertrivialResamplingBuffer msfBuffer lifoUnbounded lifoBounded lifoWatchkeepLast fifoUnbounded fifoBounded fifoWatchcollectcollectSequence pureBuffer foldBuffer ToClockProxyCl toClockProxy GetClockProxy getClockProxy ClockProxy LeafProxySequentialProxy ParallelProxyinProxyoutProxyinTagoutTag$fGetClockProxyRescaledClockS$fGetClockProxyRescaledClockM$fGetClockProxyRescaledClock$fGetClockProxyHoistClock$fGetClockProxyParallelClock$fGetClockProxySequentialClock genTimeInfo SelectClock mainClockselectschedSelectClocksschedSelectClockAndMainfilterS$fGetClockProxySelectClock$fClockmSelectClock StdinClock$fSemigroupStdinClock$fGetClockProxyStdinClock$fClockmStdinClockBusy$fGetClockProxyBusy $fClockIOBusyPureAudioClockFPureAudioClock AudioClock AudioRateHz44100Hz48000Hz96000pureAudioClockF$fGetClockProxyAudioClock$fClockmAudioClock$fAudioClockRateHz96000$fAudioClockRateHz48000$fAudioClockRateHz44100$fGetClockProxyPureAudioClock$fClockmPureAudioClockPeriodic$fGetClockProxyPeriodic$fNonemptyNatList:$fNonemptyNatList:0$fClockFreeTPeriodic BehaviorF BehaviourFBehavior BehaviourClSignalClSF hoistClSFhoistClSFAndClockliftClSFliftClSFAndClocktimelessarrMClconstMClmapMaybeSN Synchronous SequentialParallel$fToClockProxySN upsampleMSF upsampleR upsampleLcommuteReadersreaderS runReaderS runReaderS_runRandS evalRandS execRandS evalRandIOS evalRandIOS' getRandomS getRandomRS getRandomRS_BehaviorFExceptBehaviourFExcept ClSFExceptthrowSthrowpassthrowOnthrowOn' throwOnCond throwOnCondM throwMaybe runClSFExcepttryonceonce_steptimeInfo timeInfoOf sinceLastS sinceInitS absoluteStagS sinceStart>-><-<arr_clId integralFromintegralderivativeFrom derivativethreePointDerivativeFromthreePointDerivativeweightedAverageFrom averageFromaverageaverageLinFrom averageLinlowPasshighPassbandPassbandStop keepFirst historySincedelayBytimertimer_ scaledTimerlastS>>-^^->>*-*&-& timestamped>>>^^>>>****||||++++Count FixedStepstepsizescheduleFixedStepdownsampleFixedStep$fGetClockProxyFixedStep$fClockmFixedStep Millisecond waitClockdownsampleMillisecondscheduleMillisecond$fGetClockProxyMillisecond$fClockIOMillisecondlinearsinccubiceraseClockClSF eraseClockSNeraseClockResBuf EventClock EventChanTwithChan runEventChanT withChanSemitemitS emitSMaybeemit'emitS' emitSMaybe' eventClockOnconcurrentlyWithEvents$fGetClockProxyEventClock$fClockReaderTEventClock$fSemigroupEventClockRhinesnclock eraseClock$fToClockProxyRhineRhineParallelAndScheduleRhineAndResamplingPointResamplingPoint@@-@->---->++@@++||@@||flow reactimateClcommuteExceptReaderControl.Monad.Trans.ReaderReaderTcommuteReaderExceptcommuteReaderRand(MonadRandom-0.5.2-FNRj3WVb8AMAVgoNIYVDArControl.Monad.Trans.Random.LazyRandTGHC.NumNum Data.EitherEither GHC.MaybeNothingGHC.Base SemigroupMaybeghc-prim GHC.TypesFloatrateToIntegralGHC.RealIntegral GHC.Float double2FloatcycleS MSFExceptreturnBoolTrueJustFalseChanIO