[Haskell-cafe] Is this a correct explanation of FRP?

Peter Minten peter.minten at orange.nl
Sun Apr 1 10:50:10 CEST 2012


On Fri, 2012-03-30 at 02:30 +0200, Ertugrul Söylemez wrote:
> Peter Minten <peter.minten at orange.nl> wrote:
> 
> > I've been trying to get my head around Functional Reactive Programming
> > by writing a basic explanation of it, following the logic that
> > explaining something is the best way to understand it.
> >
> > Am I on the right track with this explanation?
> 
> You are explaining a particular instance of FRP.  Functional reactive
> programming is not a single concept, but a whole family of them.
> Traditional FRP as implemented by reactive-banana (and older libraries
> like Elerea, Fran and Reactive) is based on behaviors and events.  It
> uses the notion of a time-dependent value in a direct fashion.
> Conceptionally traditional FRP is this:
> 
>     Behavior a = Time -> a
>     Event a    = [(Time, a)]
> 
>     -- The current time at even seconds and half the current time at odd
>     -- seconds:
> 
>     alterTime = fullTime
>     fullTime = switch (after 1) currentTime halfTime
>     halfTime = switch (after 1) (fmap (/ 2) currentTime) fullTime
> 
> There is a second instance of FRP though called AFRP.  The A stands for
> "arrowized", but in modern times I prefer to think of it as
> "applicative".  The underlying control structure is now a category and
> the concept of a time-varying value is changed to a time-varying
> function (called signal function (SF)), which is just an automaton and
> there is an arrow for it.  This simplifies implementation, makes code
> more flexible and performance more predictable.  The libraries Animas
> and Yampa implement this concept (Animas is a fork of Yampa).
> Conceptionally:
> 
>     SF a b    = a -> (b, SF a b)
>     Event a b = SF a (Maybe b)
> 
>     alterTime = fullTime
>     fullTime = switch (after 1) currentTime halfTime
>     halfTime = switch (after 1) ((/ 2) ^<< currentTime) fullTime

Sorry, I don't understand this. Would it be correct to say that AFRP
shares the basic ideas of FRP in that it has behaviors and
events/signals and that the main difference comes from the way AFRP is
implemented?

As I see FRP it has three components: the basic concepts, the underlying
theory and the way the libraries actually work.

As far as I understand FRP (which is not very far at all) the basic
concepts can, simplified, be formulated as:

* There are things which have a different value depending on when you
look at them. (behaviors)
* It is possible to express that something has occured at a certain
point in time. (events/signals)
* Behaviors can change in response to events/signals.
* A behavior's value may be different on different points in time even
if no event has come in.

"Normal" FRP theory expresses behaviors as "Time -> a" and events as
"[(Time,a)]". AFRP uses some kind of "signal function" to express
behaviors, or behaviors are signal functions and those functions
interact with events. Anyway AFRP uses a completely different
theoretical way of thinking about events and behaviors.

The reactive-banana library uses some internal representation which
exposes an API using applicative functors. The theory behind it, as
shown in the haddock comments, is "Normal" FRP.

The reactive library uses monads and not just applicative functors. It
uses the "Normal" FRP style.

Yampa/Animas use arrows and have a different underpinning in math.
However the basic concepts of FRP are shared with all the other
libraries.

Netwire also uses AFRP but extends the theory with something called
signal inhibition. Like everything else it shares the basic concepts of
FRP.

FRP concepts -> FRP        -> reactive
                           -> reactive-banana
             -> AFRP       -> Yampa
                           -> Animas
             -> wired AFRP -> Netwire

Is this a correct way to summarize the differences?

Greetings,

Peter Minten




More information about the Haskell-Cafe mailing list