bearriver-0.14.5: FRP Yampa replacement implemented with Monadic Stream Functions.
Copyright(c) Ivan Perez 2019-2022
(c) Ivan Perez and Manuel Baerenz 2016-2018
LicenseBSD3
Maintainerivan.perez@keera.co.uk
Safe HaskellSafe-Inferred
LanguageHaskell2010

FRP.BearRiver

Description

Implementation of Yampa using Monadic Stream Processing library.

Synopsis

Signal functions

Basic signal functions

localTime :: Monad m => SF m a Time Source #

Outputs the time passed since the signal function instance was started.

time :: Monad m => SF m a Time Source #

Alternative name for localTime.

Events

mapEventS :: Monad m => MSF m a b -> MSF m (Event a) (Event b) Source #

Apply an MSF to every input. Freezes temporarily if the input is NoEvent, and continues as soon as an Event is received.

Relation to other types

eventToMaybe :: Event a -> Maybe a Source #

Convert an Event into a Maybe value.

Both types are isomorphic, where a value containing an event is mapped to a Just, and NoEvent is mapped to Nothing. There is, however, a semantic difference: a signal carrying a Maybe may change constantly, but, for a signal carrying an Event, there should be a bounded frequency such that sampling the signal faster does not render more event occurrences.

boolToEvent :: Bool -> Event () Source #

Create an event if a Bool is True.

Discrete to continuous-time signal functions

Wave-form generation

hold :: Monad m => a -> SF m (Event a) a Source #

Zero-order hold.

Converts a discrete-time signal into a continuous-time signal, by holding the last value until it changes in the input signal. The given parameter may be used for time zero, and until the first event occurs in the input signal, so hold is always well-initialized.

>>> embed (hold 1) (deltaEncode 0.1 [NoEvent, NoEvent, Event 2, NoEvent, Event 3, NoEvent])
[1,1,2,2,3,3]

Accumulators

accumBy :: Monad m => (b -> a -> b) -> b -> SF m (Event a) (Event b) Source #

Accumulator parameterized by the accumulation function.

accumHoldBy :: Monad m => (b -> a -> b) -> b -> SF m (Event a) b Source #

Zero-order hold accumulator parameterized by the accumulation function.

State keeping combinators

Loops with guaranteed well-defined feedback

loopPre :: Monad m => c -> SF m (a, c) (b, c) -> SF m a b Source #

Loop with an initial value for the signal being fed back.

Integration and differentiation

integral :: (Monad m, Fractional s, VectorSpace a s) => SF m a a Source #

Integration using the rectangle rule.

integralFrom :: (Monad m, Fractional s, VectorSpace a s) => a -> SF m a a Source #

Integrate using an auxiliary function that takes the current and the last input, the time between those samples, and the last output, and returns a new output.

derivative :: (Monad m, Fractional s, VectorSpace a s) => SF m a a Source #

A very crude version of a derivative. It simply divides the value difference by the time difference. Use at your own risk.

derivativeFrom :: (Monad m, Fractional s, VectorSpace a s) => a -> SF m a a Source #

A very crude version of a derivative. It simply divides the value difference by the time difference. Use at your own risk.

Starts from a given value for the input signal at time zero.

iterFrom :: Monad m => (a -> a -> DTime -> b -> b) -> b -> SF m a b Source #

Integrate using an auxiliary function that takes the current and the last input, the time between those samples, and the last output, and returns a new output.

Noise (random signal) sources and stochastic event sources

occasionally Source #

Arguments

:: MonadRandom m 
=> Time

The time q after which the event should be produced on average

-> b

Value to produce at time of event

-> SF m a (Event b) 

Stochastic event source with events occurring on average once every tAvg seconds. However, no more than one event results from any one sampling interval in the case of relatively sparse sampling, thus avoiding an "event backlog" should sampling become more frequent at some later point in time.

Execution/simulation

Reactimation

reactimate :: Monad m => m a -> (Bool -> m (DTime, Maybe a)) -> (Bool -> b -> m Bool) -> SF Identity a b -> m () Source #

Convenience function to run a signal function indefinitely, using a IO actions to obtain new input and process the output.

This function first runs the initialization action, which provides the initial input for the signal transformer at time 0.

Afterwards, an input sensing action is used to obtain new input (if any) and the time since the last iteration. The argument to the input sensing function indicates if it can block. If no new input is received, it is assumed to be the same as in the last iteration.

After applying the signal function to the input, the actuation IO action is executed. The first argument indicates if the output has changed, the second gives the actual output). Actuation functions may choose to ignore the first argument altogether. This action should return True if the reactimation must stop, and False if it should continue.

Note that this becomes the program's main loop, which makes using this function incompatible with GLUT, Gtk and other graphics libraries. It may also impose a sizeable constraint in larger projects in which different subparts run at different time steps. If you need to control the main loop yourself for these or other reasons, use reactInit and react.

Debugging / Step by step simulation

evalAtZero :: SF Identity a b -> a -> (b, SF Identity a b) Source #

Evaluate an SF, and return an output and an initialized SF.

WARN: Do not use this function for standard simulation. This function is intended only for debugging/testing. Apart from being potentially slower and consuming more memory, it also breaks the FRP abstraction by making samples discrete and step based.

evalAt :: SF Identity a b -> DTime -> a -> (b, SF Identity a b) Source #

Evaluate an initialized SF, and return an output and a continuation.

WARN: Do not use this function for standard simulation. This function is intended only for debugging/testing. Apart from being potentially slower and consuming more memory, it also breaks the FRP abstraction by making samples discrete and step based.

evalFuture :: SF Identity a b -> a -> DTime -> (b, SF Identity a b) Source #

Given a signal function and time delta, it moves the signal function into the future, returning a new uninitialized SF and the initial output.

While the input sample refers to the present, the time delta refers to the future (or to the time between the current sample and the next sample).

WARN: Do not use this function for standard simulation. This function is intended only for debugging/testing. Apart from being potentially slower and consuming more memory, it also breaks the FRP abstraction by making samples discrete and step based.