
Hi. I'm trying to understand what Functional Reactive Programming is, or, more properly, what distinguishes it from "regular" functional programming, and what it would look like if I were to program in a "FRP Style", i.e., without some mysterious FRP module hiding the details. After reading a bunch of links and even looking at some source code I'm still not clear on this. If I program in an event-based style, and have data structures updating over time, with some data structures dependent on others for their values, and I use a functional language, is that FRP? Or is there some essential element I'm missing here? -- frigidcode.com indicium.us

Christopher Howard
Hi. I'm trying to understand what Functional Reactive Programming is, or, more properly, what distinguishes it from "regular" functional programming, and what it would look like if I were to program in a "FRP Style", i.e., without some mysterious FRP module hiding the details. After reading a bunch of links and even looking at some source code I'm still not clear on this.
If I program in an event-based style, and have data structures updating over time, with some data structures dependent on others for their values, and I use a functional language, is that FRP? Or is there some essential element I'm missing here?
Yes. FRP is about domain-specific languages that capture the notion of time-varying values. Let me take Netwire 4 as an example. It's not on Hackage yet, so you may want to grab it using darcs: darcs get http://darcs.ertes.de/netwire/ Imagine you have a simple GUI label that displays the number of seconds passed since program start. In an event-based model this is actually quite a complicated task. You would have to create a label and update it all the time using some form of timer/idle event. In Netwire you write: myLabel = time Now let's say you want to have the same GUI, but the time should start at 10 and pass twice as fast, so you actually want to display twice the number of seconds passed plus 10: myLabel = 10 + 2*time Imagine you want to display the string "yes" in a label: myLabel = "yes" Now let's say you want to display "yes", when the space key is held down and "no" otherwise: myLabel = "yes" . keyDown Space <|> "no" You want to display time while pressed and "Press space" while not: myLabel = fmap show time . keyDown Space <|> "no" You want to display "yes" every other second and "no" otherwise: myLabel = "yes" . holdFor 1 (periodically 2) <|> "no" Imagine doing that with event-based code. Summary: FRP is about handling time-varying values like they were regular values. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.

Ertugrul Söylemez
You want to display time while pressed and "Press space" while not:
myLabel = fmap show time . keyDown Space <|> "no"
Typo: myLabel = fmap show time . keyDown Space <|> "Press space" Of course. =) Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.

On 09/15/2012 11:16 PM, Ertugrul Söylemez wrote:
Summary: FRP is about handling time-varying values like they were regular values.
Ouch!... Ouch!... My head is beginning to explode! So, I think I understand the main idea you just explained, but now I am curious about how this black magic is possible. Presumably, these mystical "time-varying values" would actually have to be some kind of partially applied function that receives a time parameter. But how do we, as in your example, add a literal number to a function? -- frigidcode.com indicium.us

Christopher Howard
Summary: FRP is about handling time-varying values like they were regular values.
Ouch!... Ouch!... My head is beginning to explode!
So, I think I understand the main idea you just explained, but now I am curious about how this black magic is possible. Presumably, these mystical "time-varying values" would actually have to be some kind of partially applied function that receives a time parameter. But how do we, as in your example, add a literal number to a function?
One very simple and naive way to implement FRP is this: newtype Behavior a = Behavior (Time -> a) 'Behavior' is the traditional name for a time-varying value. Then a constant is, as the name says, a constant: instance Applicative Behavior where pure = Behavior . const {- ... -} To get the notation I have used you just need Haskell's fromInteger magic: instance (Num a) => Num (Behavior a) where (+) = liftA2 (+) (-) = liftA2 (-) {- ... -} fromInteger = pure . fromInteger Given that and a behavior that returns the current time, time :: Behavior Time time = Behavior id you can now have 10 + 2*time Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.

Hello Ertugrul, Can I use your explanation for the HaskellWiki FRP page[0]? Regards, Henk-Jan van Tuyl [0] http://www.haskell.org/haskellwiki/Functional_Reactive_Programming -- http://Van.Tuyl.eu/ http://members.chello.nl/hjgtuyl/tourdemonad.html Haskell programming --

Christopher Howard wrote:
On 09/15/2012 11:16 PM, Ertugrul Söylemez wrote:
Summary: FRP is about handling time-varying values like they were regular values.
Ouch!... Ouch!... My head is beginning to explode!
So, I think I understand the main idea you just explained, but now I am curious about how this black magic is possible. Presumably, these mystical "time-varying values" would actually have to be some kind of partially applied function that receives a time parameter. But how do we, as in your example, add a literal number to a function?
As Ertugrul indicated, you first turn the literal number into a function (namely the constant function) and then perform arithmetic with that function. I have a few slides that may useful in understanding the "time-varying values as ordinary values" point better http://apfelmus.nfshost.com/blog/2012/07/15-frp-tutorial-slides.html Of course, keep in mind that at the end of the day, the Behavior and Event types are going to be opaque. This is because the literal Behavior a = Time -> a implementation would be very inefficient. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

On 09/16/2012 09:16 AM, Ertugrul Söylemez wrote:
Christopher Howard
wrote: Let me take Netwire 4 as an example. It's not on Hackage yet, so you may want to grab it using darcs: darcs get http://darcs.ertes.de/netwire/
I must admit netwire 4 catched my interest. Would you consider it ready enough to try it or will I (beeing still more or less a haskell novice) despair of it? Regards, Nathan

Nathan Hüsken
I must admit netwire 4 catched my interest. Would you consider it ready enough to try it or will I (beeing still more or less a haskell novice) despair of it?
Install it with documentation enabled. There is a quickstart tutorial in the Control.Wire module, so just open its Haddock documentation: cd netwire cabal install --enable-documentation Assuming a Unix-like OS the documentation will be installed in ~/.cabal/share/doc/. Open the index.html and select the Control.Wire module. To install with documentation by default just uncomment and set 'documentation' to True in your ~/.cabal/config. The tutorial says that it's for the experienced, impatient Haskell programmer, but it should be quite accessible even for beginners who understand the syntax and the basics of the type system. You can use it in production, because the interface won't change anymore. I'm just improving documentation and adding some further utilities before the official release. Feedback is very much appreciated. =) Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.
participants (5)
-
Christopher Howard
-
Ertugrul Söylemez
-
Heinrich Apfelmus
-
Henk-Jan van Tuyl
-
Nathan Hüsken