After reading many pages about FRP I finally came across this enlightening writing about FRP, it finally made me understand what FRP really is all about.

I quote below Heinrich Apfelmus (author of reactive banana).

What is the essence of functional reactive programming?

A common answer would be that “FRP is all about describing a system in

terms of time-varying functions instead of mutable state”, and that

would certainly not be wrong. This is the semantic viewpoint. But in

my opinion, the deeper, more satisfying answer is given by the

following purely syntactic criterion:

The essence of functional reactive programming is to specify the dynamic behavior of a value completely at the time of declaration.For instance, take the example of a counter: you have two buttons

labelled “Up” and “Down” which can be used to increment or decrement

the counter. Imperatively, you would first specify an initial value

and then change it whenever a button is pressed; something like this:`counter := 0 -- initial value on buttonUp = (counter := counter + 1) -- change it later on buttonDown = (counter := counter - 1)`

The point is that at the time of declaration, only the initial value

for the counter is specified; the dynamic behavior of counter is

implicit in the rest of the program text. In contrast, functional

reactive programming specifies the whole dynamic behavior at the time

of declaration, like this:`counter :: Behavior Int counter = accumulate ($) 0 (fmap (+1) eventUp `union` fmap (subtract 1) eventDown)`

Whenever you want to understand the dynamics of counter, you only have

to look at its definition. Everything that can happen to it will

appear on the right-hand side. This is very much in contrast to the

imperative approach where subsequent declarations can change the

dynamic behavior of previously declared values.

So, in **my understanding** an FRP program is a set of equations:

`j`

is discrete: 1,2,3,4…

`f`

depends on `t`

so this incorporates the possiblilty to model external stimuli

all state of the program is encapsulated in variables `x_i`

The FRP library takes care of progressing time, in other words, taking `j`

to `j+1`

.

I explain these equations in much more detail in this video.

**EDIT:**

About 2 years after the original answer, recently I came to the conclusion that FRP implementations have another important aspect. They need to (and usually do) solve an important practical problem: **cache invalidation**.

The equations for `x_i`

-s describe a dependency graph. When some of the `x_i`

changes at time `j`

then not all the other `x_i'`

values at `j+1`

need to be updated, so not all the dependencies need to be recalculated because some `x_i'`

might be independent from `x_i`

.

Furthermore, `x_i`

-s that do change can be incrementally updated. For example let’s consider a map operation `f=g.map(_+1)`

in Scala, where `f`

and `g`

are `List`

of `Ints`

. Here `f`

corresponds to `x_i(t_j)`

and `g`

is `x_j(t_j)`

. Now if I prepend an element to `g`

then it would be wasteful to carry out the `map`

operation for all the elements in `g`

. Some FRP implementations (for example reflex-frp) aim to solve this problem. This problem is also known as incremental computing.

In other words, behaviours (the `x_i`

-s ) in FRP can be thought as cache-ed computations. It is the task of the FRP engine to efficiently invalidate and recompute these cache-s (the `x_i`

-s) if some of the `f_i`

-s do change.