[Edit]: change "form of FRP" to "form of reactive programming" as I'm not sure I know the true notion of "FRP" based on tel's response.
You could probably say that this library implements a form of reactive programming using transducers with `asCallback` and `asyncCallback`. In fact, many ideas for this library were rooted in my exploration of ReactiveCocoa a few years back [1]. I think that transducers lead to a much cleaner implementation and I may resurrect that library to be based on underscore-transducer and add more reactive extensions. (Also, the 'r' in `_r` stands for "reactive".)
I really like the way transducers abstract the process of iteration from the transformation that makes this possible.
To be honest, FRP is a dicey term. The original definition was rather clear arising from Elliott and Hudak's work on things like Fran and The Haskell School of Expression. It clearly spoke to the a need to a) represent values as time-varying instead of fixed and b) to encode "continuous time" and these features became known as FRP.
(I'd also add in Elliott's denotational design aspects, but those sort of become dicier with respect to arrowized FRP.)
Reactive Programming is a more general term and is often applied to any kind of synchronous (and sometimes even asynchronous) stream processing. I think it's utter buzz and appreciate Eric Meijer's talk[0] about what "reactive" tends to mean (push and pull streams, fine tuned effect handling).
Now, if you're doing regular old stream processing then you can hook up whatever kind of event handlers you like, push and pull. Transducers form a framework for achieving some of these kinds of transformations as they encode one-to-many transforms (with ambient local state as available in Clojure and all the early termination business, but basically just a -> [b]). In some sense they're nearly "arrowized" as you're focusing on the transformation of "reactive" quantities, but they're certainly discretized and tied to sampling rates in their formulation.
Very interesting. I certainly have some reading to do.
Can you explain a little more the notion discrete values and sampling rates and how that applies to stream processing? I assume that it applies to sampling values of a process over time, but what would be an example in computation where the value would be considered continuous? Is it similar to continuous vs discrete signal processing?
It's very similar to continuous/discrete DSP. The classic example is the integral or the feedback loop. We often talk about circuits which have continuous logic in terms of integrators and feedback loops. Direct from [0] we have a computation of
Exp[t] = 1 + Integral[Exp[x], {x, 0, t}]
as
exp :: SF () Double
exp = proc () -> do
rec let e = 1 + i
i <- integral −< e
returnA −< e
The integral is approximate (of course) but the algorithm holds to approximation no matter what the sampling rate is---that can be chosen by the consumer of the algorithm. From [1] you have an example from a vision system where the algorithm is specified in physical terms w.r.t. the motion of vehicles within a video frame. Again, the sampling occurs when the FRP computation is executed not when it's constructed.
Probably the most tangible example for this audience is thinking about Javascript GUIs. A Javascript GUI might be thought of as depending upon continuous signals like the mouse position, current time, scroll position, etc and also a set of (instantaneous) events like mouse clicks, new data arriving from asynchronous requests, etc. The output is a continuous "state of the GUI" signal.
Ultimately, the actual mouse position and painting loops are discrete, obviously, but their sample rates may be chosen independently of the actual business logic.
FRP and transducers don't have much to do with one another at all. Transducers involve construction of processor pipelines ("roughly", a bunch of chained flatmaps/list monad binds). FRP is an abstraction over synchronous reactive programming which hides sample rate.
Reactive Programming is thrown in there for good measure as well, but typically "reactive" applies to anything which is synchronous or asynchronous programming but usually does not abstract sampling rate at all.
The upshot is that FRP is the most uncertain today and also the most composable. Reactive Programming is mostly programming with asynchronous streams and is a little ad hoc and, ultimately, a really wide space of approaches.
Transducers are a very particular tool for constructing "container transformers" which might be used to build some small piece of a reactive programming system. Mostly likely they'll not be used in a true FRP system because they understand the notion of discrete updates which break the composability of FRP.
Comments
Interesting, how does this relate to FRP? The examples at http://simplectic.com/projects/underscore-transducer/ are similar to hello-world examples in Bacon.js or RxJS.
[Edit]: change "form of FRP" to "form of reactive programming" as I'm not sure I know the true notion of "FRP" based on tel's response.
You could probably say that this library implements a form of reactive programming using transducers with `asCallback` and `asyncCallback`. In fact, many ideas for this library were rooted in my exploration of ReactiveCocoa a few years back [1]. I think that transducers lead to a much cleaner implementation and I may resurrect that library to be based on underscore-transducer and add more reactive extensions. (Also, the 'r' in `_r` stands for "reactive".)
I really like the way transducers abstract the process of iteration from the transformation that makes this possible.
[1]: https://github.com/kevinbeaty/underarm
To be honest, FRP is a dicey term. The original definition was rather clear arising from Elliott and Hudak's work on things like Fran and The Haskell School of Expression. It clearly spoke to the a need to a) represent values as time-varying instead of fixed and b) to encode "continuous time" and these features became known as FRP.
(I'd also add in Elliott's denotational design aspects, but those sort of become dicier with respect to arrowized FRP.)
Reactive Programming is a more general term and is often applied to any kind of synchronous (and sometimes even asynchronous) stream processing. I think it's utter buzz and appreciate Eric Meijer's talk[0] about what "reactive" tends to mean (push and pull streams, fine tuned effect handling).
Now, if you're doing regular old stream processing then you can hook up whatever kind of event handlers you like, push and pull. Transducers form a framework for achieving some of these kinds of transformations as they encode one-to-many transforms (with ambient local state as available in Clojure and all the early termination business, but basically just a -> [b]). In some sense they're nearly "arrowized" as you're focusing on the transformation of "reactive" quantities, but they're certainly discretized and tied to sampling rates in their formulation.
[0] http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Key...
Very interesting. I certainly have some reading to do.
Can you explain a little more the notion discrete values and sampling rates and how that applies to stream processing? I assume that it applies to sampling values of a process over time, but what would be an example in computation where the value would be considered continuous? Is it similar to continuous vs discrete signal processing?
It's very similar to continuous/discrete DSP. The classic example is the integral or the feedback loop. We often talk about circuits which have continuous logic in terms of integrators and feedback loops. Direct from [0] we have a computation of
as The integral is approximate (of course) but the algorithm holds to approximation no matter what the sampling rate is---that can be chosen by the consumer of the algorithm. From [1] you have an example from a vision system where the algorithm is specified in physical terms w.r.t. the motion of vehicles within a video frame. Again, the sampling occurs when the FRP computation is executed not when it's constructed.Probably the most tangible example for this audience is thinking about Javascript GUIs. A Javascript GUI might be thought of as depending upon continuous signals like the mouse position, current time, scroll position, etc and also a set of (instantaneous) events like mouse clicks, new data arriving from asynchronous requests, etc. The output is a continuous "state of the GUI" signal.
Ultimately, the actual mouse position and painting loops are discrete, obviously, but their sample rates may be chosen independently of the actual business logic.
[0] Liu, Cheng, Hudak. Causal Commutative Arrows and Their Optimization. http://cs.yale.edu/c2/images/uploads/ICFP-CCA.pdf
[1] Nilsson, Courtney, Peterson. Functional Reactive Programming, Continued. http://haskell.cs.yale.edu/wp-content/uploads/2011/02/worksh...
Thanks, that explains a lot. Very interesting indeed.
FRP and transducers don't have much to do with one another at all. Transducers involve construction of processor pipelines ("roughly", a bunch of chained flatmaps/list monad binds). FRP is an abstraction over synchronous reactive programming which hides sample rate.
Reactive Programming is thrown in there for good measure as well, but typically "reactive" applies to anything which is synchronous or asynchronous programming but usually does not abstract sampling rate at all.
The upshot is that FRP is the most uncertain today and also the most composable. Reactive Programming is mostly programming with asynchronous streams and is a little ad hoc and, ultimately, a really wide space of approaches.
Transducers are a very particular tool for constructing "container transformers" which might be used to build some small piece of a reactive programming system. Mostly likely they'll not be used in a true FRP system because they understand the notion of discrete updates which break the composability of FRP.