Search code examples
haskellfrpyampa

Continual signal switching in arrowized FRP


I've been playing around with Arrowized FRP libraries in Haskell (Yampa, in particular), but I can't quite figure out how to do "continual" switching. By that I mean that a signal passes through a signal function (sf below) which is itself a signal (as drawn in the upper half of the image).

Continual switching

Since I don't know ahead of time what the parameters of the switch will be, I can't see how to reduce this to a simpler, binary switch.

How then should one do it, if it's possible at all? I'd prefer Yampa code, but am happy with any Arrowized FRP code. I haven't tried other libraries (e.g. Sodium or Reactive Banana) to know whether I'd have the same confusion in those cases, but I'm curious about them too.

EDIT

To make this clearer an more concrete, I've labeled the image; possible types for the labels are:

  • in: Either Int (Int -> Int)

  • 1: (Int -> Int) -> (Either Int (Int -> Int) -> (Int -> Int))

  • sf could be:

(Either Int (Int -> Int) -> (Int -> Int)) -> Either Int (Int -> Int) -> (Int -> Int)

(e.g., app). But that's only if the part labeled with a question mark represents an input into sf. If it represents a more complex switch, the type would be

(Either Int (Int -> Int) -> (Int -> Int)) -> (Int -> Int)

instead.

  • 2 and out are pretty much irrelevant.

The idea is that I want the circuit to behave as if sf were app, with the signal labeled f representing the function that is applied to in, and with in itself being the source of both the arguments to fs, and the fs themselves. I want to get a circuit that can process inputs and change it's behavior (the signal functions that constitute it) dynamically based on those inputs.

On the one hand, it seems to me like sf can't in fact be app, since in this case we don't have an ArrowApply; but on the other hand I imagine that same behavior can be achieved with some form of sophisticated switching.


Solution

  • I still think it's a case of ArrowLoop!

    You have

    in :: Arr () A
    sf :: Arr (A -> B, A) B
    one :: Arr B (A -> B)
    two :: Arr B C
    

    sf is just arr (uncurry ($)).

    Then you have sf >>> (one &&& two) :: Arr (A -> B, A) (A -> B, C) and you can use loop (or rather loop with arr swap judiciously placed) to get an Arr A C.

    Will that give you what you want?