Copyright | (c) Antony Courtney and Henrik Nilsson Yale University 2003 |
---|---|

License | BSD-style (see the LICENSE file in the distribution) |

Maintainer | ivan.perez@keera.co.uk |

Stability | provisional |

Portability | non-portable (GHC extensions) |

Safe Haskell | None |

Language | Haskell98 |

Switches allow you to change the signal function being applied.

The basic idea of switching is fromed by combining a subordinate signal function and a signal function continuation parameterised over some initial data.

For example, the most basic switch has the following signature:

switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b

which indicates that it has two parameters: a signal function that produces an output and indicates, with an event, when it is time to switch, and a signal function that starts with the residual data left by the first SF in the event and continues onwards.

Note that switching occurs, at most, once. If you want something to switch repeatedly, you need to loop. However, some switches are immediate (meaning that the second SF is started at the time of switching). If you use the same SF that originally provoked the switch, you are very likely to fall into an infinite loop.

- switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b
- dSwitch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b
- rSwitch :: SF a b -> SF (a, Event (SF a b)) b
- drSwitch :: SF a b -> SF (a, Event (SF a b)) b
- kSwitch :: SF a b -> SF (a, b) (Event c) -> (SF a b -> c -> SF a b) -> SF a b
- dkSwitch :: SF a b -> SF (a, b) (Event c) -> (SF a b -> c -> SF a b) -> SF a b
- parB :: Functor col => col (SF a b) -> SF a (col b)
- pSwitchB :: Functor col => col (SF a b) -> SF (a, col b) (Event c) -> (col (SF a b) -> c -> SF a (col b)) -> SF a (col b)
- dpSwitchB :: Functor col => col (SF a b) -> SF (a, col b) (Event c) -> (col (SF a b) -> c -> SF a (col b)) -> SF a (col b)
- rpSwitchB :: Functor col => col (SF a b) -> SF (a, Event (col (SF a b) -> col (SF a b))) (col b)
- drpSwitchB :: Functor col => col (SF a b) -> SF (a, Event (col (SF a b) -> col (SF a b))) (col b)
- par :: Functor col => (forall sf. a -> col sf -> col (b, sf)) -> col (SF b c) -> SF a (col c)
- pSwitch :: Functor col => (forall sf. a -> col sf -> col (b, sf)) -> col (SF b c) -> SF (a, col c) (Event d) -> (col (SF b c) -> d -> SF a (col c)) -> SF a (col c)
- dpSwitch :: Functor col => (forall sf. a -> col sf -> col (b, sf)) -> col (SF b c) -> SF (a, col c) (Event d) -> (col (SF b c) -> d -> SF a (col c)) -> SF a (col c)
- rpSwitch :: Functor col => (forall sf. a -> col sf -> col (b, sf)) -> col (SF b c) -> SF (a, Event (col (SF b c) -> col (SF b c))) (col c)
- drpSwitch :: Functor col => (forall sf. a -> col sf -> col (b, sf)) -> col (SF b c) -> SF (a, Event (col (SF b c) -> col (SF b c))) (col c)
- parZ :: [SF a b] -> SF [a] [b]
- pSwitchZ :: [SF a b] -> SF ([a], [b]) (Event c) -> ([SF a b] -> c -> SF [a] [b]) -> SF [a] [b]
- dpSwitchZ :: [SF a b] -> SF ([a], [b]) (Event c) -> ([SF a b] -> c -> SF [a] [b]) -> SF [a] [b]
- rpSwitchZ :: [SF a b] -> SF ([a], Event ([SF a b] -> [SF a b])) [b]
- drpSwitchZ :: [SF a b] -> SF ([a], Event ([SF a b] -> [SF a b])) [b]
- parC :: SF a b -> SF [a] [b]

# Switching

## Basic switchers

switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b #

Basic switch.

By default, the first signal function is applied.

Whenever the second value in the pair actually is an event, the value carried by the event is used to obtain a new signal function to be applied *at that time and at future times*.

Until that happens, the first value in the pair is produced in the output signal.

Important note: at the time of switching, the second signal function is applied immediately. If that second SF can also switch at time zero, then a double (nested) switch might take place. If the second SF refers to the first one, the switch might take place infinitely many times and never be resolved.

Remember: The continuation is evaluated strictly at the time of switching!

dSwitch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b #

Switch with delayed observation.

By default, the first signal function is applied.

Whenever the second value in the pair actually is an event, the value carried by the event is used to obtain a new signal function to be applied *at future times*.

Until that happens, the first value in the pair is produced in the output signal.

Important note: at the time of switching, the second signal function is used immediately, but the current input is fed by it (even though the actual output signal value at time 0 is discarded).

If that second SF can also switch at time zero, then a double (nested) -- switch might take place. If the second SF refers to the first one, the switch might take place infinitely many times and never be resolved.

Remember: The continuation is evaluated strictly at the time of switching!

rSwitch :: SF a b -> SF (a, Event (SF a b)) b #

Recurring switch.

See https://wiki.haskell.org/Yampa#Switches for more information on how this switch works.

drSwitch :: SF a b -> SF (a, Event (SF a b)) b #

Recurring switch with delayed observation.

See https://wiki.haskell.org/Yampa#Switches for more information on how this switch works.

kSwitch :: SF a b -> SF (a, b) (Event c) -> (SF a b -> c -> SF a b) -> SF a b #

Call-with-current-continuation switch.

See https://wiki.haskell.org/Yampa#Switches for more information on how this switch works.

dkSwitch :: SF a b -> SF (a, b) (Event c) -> (SF a b -> c -> SF a b) -> SF a b #

`kSwitch`

with delayed observation.

See https://wiki.haskell.org/Yampa#Switches for more information on how this switch works.

## Parallel composition and switching

### Parallel composition and switching over collections with broadcasting

parB :: Functor col => col (SF a b) -> SF a (col b) #

Spatial parallel composition of a signal function collection.
Given a collection of signal functions, it returns a signal
function that `broadcast`

s its input signal to every element
of the collection, to return a signal carrying a collection
of outputs. See `par`

.

For more information on how parallel composition works, check http://haskell.cs.yale.edu/wp-content/uploads/2011/01/yampa-arcade.pdf

pSwitchB :: Functor col => col (SF a b) -> SF (a, col b) (Event c) -> (col (SF a b) -> c -> SF a (col b)) -> SF a (col b) #

Parallel switch (dynamic collection of signal functions spatially composed
in parallel). See `pSwitch`

.

For more information on how parallel composition works, check http://haskell.cs.yale.edu/wp-content/uploads/2011/01/yampa-arcade.pdf

dpSwitchB :: Functor col => col (SF a b) -> SF (a, col b) (Event c) -> (col (SF a b) -> c -> SF a (col b)) -> SF a (col b) #

Delayed parallel switch with broadcasting (dynamic collection of
signal functions spatially composed in parallel). See `dpSwitch`

.

For more information on how parallel composition works, check http://haskell.cs.yale.edu/wp-content/uploads/2011/01/yampa-arcade.pdf

### Parallel composition and switching over collections with general routing

:: Functor col | |

=> (forall sf. a -> col sf -> col (b, sf)) | Determines the input to each signal function in the collection. IMPORTANT! The routing function MUST preserve the structure of the signal function collection. |

-> col (SF b c) | Signal function collection. |

-> SF a (col c) |

Spatial parallel composition of a signal function collection parameterized on the routing function.

:: Functor col | |

=> (forall sf. a -> col sf -> col (b, sf)) | Routing function: determines the input to each signal function in the collection. IMPORTANT! The routing function has an obligation to preserve the structure of the signal function collection. |

-> col (SF b c) | Signal function collection. |

-> SF (a, col c) (Event d) | Signal function generating the switching event. |

-> (col (SF b c) -> d -> SF a (col c)) | Continuation to be invoked once event occurs. |

-> SF a (col c) |

Parallel switch parameterized on the routing function. This is the most general switch from which all other (non-delayed) switches in principle can be derived. The signal function collection is spatially composed in parallel and run until the event signal function has an occurrence. Once the switching event occurs, all signal function are "frozen" and their continuations are passed to the continuation function, along with the event value.

:: Functor col | |

=> (forall sf. a -> col sf -> col (b, sf)) | Routing function. Its purpose is
to pair up each running signal function in the collection
maintained by |

-> col (SF b c) | Initial collection of signal functions. |

-> SF (a, col c) (Event d) | Signal function that observes the external input signal and the output signals from the collection in order to produce a switching event. |

-> (col (SF b c) -> d -> SF a (col c)) | The fourth argument is a function that is invoked when the
switching event occurs, yielding a new signal function to switch
into based on the collection of signal functions previously
running and the value carried by the switching event. This
allows the collection to be updated and then switched back
in, typically by employing |

-> SF a (col c) |

Parallel switch with delayed observation parameterized on the routing function.

The collection argument to the function invoked on the
switching event is of particular interest: it captures the
continuations of the signal functions running in the collection
maintained by `dpSwitch`

at the time of the switching event,
thus making it possible to preserve their state across a switch.
Since the continuations are plain, ordinary signal functions,
they can be resumed, discarded, stored, or combined with
other signal functions.

rpSwitch :: Functor col => (forall sf. a -> col sf -> col (b, sf)) -> col (SF b c) -> SF (a, Event (col (SF b c) -> col (SF b c))) (col c) #