All of the switch
functions are ways to change a signal function to behave like another signal function. I personally find the Yampa diagrams to be somewhat difficult to parse, but the type signatures of the various switches give good indication for how to understand them. Once you understand the type signatures, the diagrams become much clearer. switch
itself is the most basic:
switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b
If we look at the type, it tells us exactly what it does: It takes a SF sf
and a SF generator sfg
. sf
produces values of type (b, Event c)
, and the input to the signal function generator happens to also be of type c
. So, whenever sf
's event occurs, the SF will switch to the result of the SF generator. Until an event occurs, the resulting SF will return the value of the original SF.
This idea is also used in the rswitch
and kswitch
variants but a bit differently.
rswitch
: This is known as an "extrinsic switch", meaning that the SF will switch without any analysis of its input or output. Let's look at the type signature:
rswitch :: SF a b -> SF (a, Event (SF a b)) b
It takes a single SF that takes as input values of type a
and outputs values of type b
. rswitch
creates a new SF that also produces output b
, but takes an additional input of type Event (SF a b)
. Note that the Event value's type matches the input type. This means that whenever the event happens, this SF will switch to that event value. However, the type of the SF remains SF (a, Event (SF a b)) b
. This means that the SF is free to receive additional events with new SFs, which will influence the behavior of the overall SF. One use for this could be AI behaviors in a game:
moveFollowTarget :: SF TargetPosition Velocity
moveShootTarget :: SF TargetPosition Velocity
moveIdle :: SF TargetPosition Velocity
aiMovement :: SF (TargetPosition, Event (SF TargetPosition Velocity)) Velocity
aiMovement = rswitch moveIdle -- Initially idle...
aiMovementManager :: SF a (Event (SF TargetPosition Velocity))
aiMovementManager = ... whatever ...
Here, the aiMovementManager
will fire an event whenever the movement behavior of the AI needs to change, and the value of the event will be the SF that the movement should change to.
kswitch
: This is known as an intrinsic switch
, since the contents of the SF are analyzed to figure out what the proper switch should be. Let's go over the type signature
kswitch :: SF a b -> SF (a, b) (Event c) -> (SF a b -> c -> SF a b) -> SF a b
Here, kswitch
takes three arguments, sf
, analyzer
, and mapping
. sf
is simply a standard SF with inputs of type a
and outputs of type b
. sf
is how the signal behaves initially. analyzer
is a SF that takes the input and output of sf
and may or may not fire some sort of event whose value has type c
. If it doesn't fire an event, then nothing happens, and the SF continues to behave like sf
. If it does fire an event, then both sf
and the event value are passed to mapping
which determines the new SF to switch to. kswitch
is useful when changing the way systems behave based on their outputs.
One example where this is useful is the algorithm for TCP Congestion Avoidance. Here, we look at whether or not we lose network packets, and either increase or decrease the speed at which we request data.