
Hi Tom,
I don't think this is really true. Behaviors and Events do not reveal in their type definitions any relation to any system that they may or may not exist in.
OK. So how does e.g. mousePoint :: Behavior Point get at the mouse input? unsafePerformIO? I.e. it is conceptually a global signal?
I'm not sure I understand you clearly. If I wish to apply a constant function to a signal, can I not just use fmap?
The question is why I would want to (conceptually). I'm just saying I find it good and useful to be able to easily mix static values and computations and signals and computations on signals.
You would certainly need to ask Conal on this point, but I have no reason to suspect that b' = [1,2,3,4,5] `stepper` listE [(1,[])] would > not deallocate the first list once it had taken its step.
It's not the lists that concern me, nor getting rid of a collection of behaviors all at once. The problem is if we ant to run a collection of behaviors in parallel, all potentially accumulating internal state, how do we add/delete individual behaviors to/from that collection, without "disturbing" the others? For the sake of argument, say we have the following list of behaviours: [integral time, integral (2 * time), integral (3 * time)] We turn them into a single behavior with a list output in order to run them. After one second the output is thus [1,2,3] Now, we want to delete the second behavior, but continue to run the other two, so that the output at time 2 is [2,6] Simply mapping postprocessing that just drops the second element from the output isn't a satisfactory solution.
let n :: Behavior Int n = <behaviour that counts left mouse button clicks> in n `until` <some event> -=> n
I'm not sure I got the syntax right. But the idea is that we output the number of left mouse button clicks, and then at some point, we switch to a behavior that again output the number of left mouse button clicks, notionally the "same" one "n".
The question is, after the switch, do we observe a count that continues from where the old one left off, i.e. is there a single *shared* instance of "n" that is merely being *observed* from within the two "branches" of the switch, or is the counting behavior "n" restarted (from 0) after the switch?
Yes, we really do get a shared n -- without doing that we certainly would see a large space/time leak.
Interesting, although I don't see why not sharing would imply a space/time leak: if the behavior is simply restarted, there is no catchup computation to do, nor any old input to hang onto, so there is neither a time nor a space-leak? Anyway, let's explore this example a bit further. Suppose "lbp" is the signal of left button presses, and that we can count them by "count lbp" Then the question is if let n :: Behavior Int n = count lbp in n `until` <some event> -=> n means the same as (count lbp) `until` <some event> -=> (count lbp) If no, then Reactive is not referentially transparent, as we manifestly cannot reason equationally. If yes, the question is how to express a counting that starts over after the switch (which sometimes is what is needed).
Yep, such Behaviors are seperated in Reactive only by the method you create them with. I may use the `stepper` function to create a behavior that increases in steps based on an event occurring, or I may > use fmap over time to create a continuously varying Behavior.
But the question was not about events vs continuous signals. The question is, what is a behavior conceptually, and when is it started? E.g. in the example above, at what point do the various instances of "count lbp" start counting? Or are the various instances of "count lbp" actually only one? Or if you prefer, are beahviours really signals, that conceptually start running all at once at a common time 0 when the system starts? The answers regarding input behaviors like mousePosition, that "n is shared", and the need to do catchup computations all seem to indicate this. But if so, that leaves open an important question on expressivity, examplified by how to start counting from the time of a switch above, and makes if virtually impossible to avoid time and space leaks in general, at least in an embedded setting. After all, something like "count lbp" can be compiled into a function that potentially may be invoked at some point. And as long as this possibility exists, the system needs to hang on to the entire history of mouse clicks so that they can be coounted at some future point if necessary. These are all questions that go back to classical FRP, which we didn't find any good answers to back then, and which also were part of the motivation for moving to AFRP/Yampa. If Reactive has come up with better answers, that would be very exciting indeed! Best, /Henrik -- Henrik Nilsson School of Computer Science The University of Nottingham nhn@cs.nott.ac.uk This message has been checked for viruses but the contents of an attachment may still contain software viruses, which could damage your computer system: you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation.