Functional Reactive
Programming
FP, Javascript y extra de bacon
Slide 2
Slide 2 text
Javier Onielfa Belenguer
Software Engineer @ R&D Astellia Spain
@onielfadev
Slide 3
Slide 3 text
Summary
1. Functional Programming
2. Theory
a. Classical FRP
b. Transformations
3. Coding
a. Architecture
b. Examples
4. Implementations and problems
a. Advantages/Disavantages
b. Implementation
5. References
Slide 4
Slide 4 text
Functional
Programming?
Slide 5
Slide 5 text
FP Crash Course
Slide 6
Slide 6 text
Functional Programming
● Functional programming is programming with functions
● Functions are first class citizens: You can pass them, return them
and store them in datastructures.
● Functions tend to be pure. The evaluation of a function ONLY
depends on its inputs.
● Equational reasoning.
● Embraces a data-oriented view. You are transforming data.
Slide 7
Slide 7 text
Let’s begin
Slide 8
Slide 8 text
Programming viewed as transforming data
INPUT
COMPUTER
PROGRAM
DATA DATA
OUTPUT
Slide 9
Slide 9 text
Examples
INPUT
WEB SERVER
PROCESS
HTTP
REQ
HTTP
RES
OUTPUT
INPUT
ALGORITHM
PROCESS
PROBLEM SOLUTION
OUTPUT
INPUT
WEB APP
PROCESS
UI
EVENT
HTML
REDRAW
OUTPUT
Slide 10
Slide 10 text
Real world apps don’t receive only one
piece of data.
What’s missing?
Slide 11
Slide 11 text
Real world apps don’t receive only one
piece of data.
What’s missing?
TIME
Slide 12
Slide 12 text
Facing values that change over time
app.post('/process-file', function(req, res) {
var inputFile = 'input.txt';
var outputFile = 'output.txt';
fs.readFile(inputFile, function(err, data) {
if (err) return res.status(500).send(err);
process1(data, function(err, data) {
if (err) return res.status(500).send(err);
process2(data, function(err, data) {
if (err) return res.status(500).send(err);
process3(data, function(err, data) {
if (err) return res.status(500).send(err);
fs.writeFile(outputFile, data, function(err) {
if (err) return res.status(500).send(err);
res.status(200).send('processed successfully using callback hell');
});
});
});
});
});
});
Slide 13
Slide 13 text
Classic FRP
As semantically defined in Functional Reactive Animation, Conal
Elliot et al, 1998.
Behavior
● It’s a function of time
○ type Behavior :: T -> a
● Continuous time-varying values.
● Sample rate independent.
● Introduced for modelling animation/physics (velocity, gravity,etc)
● Inefficient implementation. Led to space leaks.
Slide 14
Slide 14 text
Classic FRP
As semantically defined in Functional Reactive Animation, Conal
Elliot et al, 1998.
EventSource
● Stream of timed values.
○ type EventSource :: [(T,a)] where Tn < Tn+1
● Discrete time values.
● It’s like you are in another dimension where you can see
the past, present and future. The whole timeline.
● Fits perfectly for heavily event oriented applications.
Slide 15
Slide 15 text
“There is no future. There is no
past… Time is simultaneous, an
intricately structured jewel that
humans insist on viewing one
edge at a time, when the whole
design is visible in every facet.”
Dr. Manhattan, Watchmen
Slide 16
Slide 16 text
C
1s
Keystrokes O
3s
D E
7s
M
9s
O
12s
4s
Keystrokes = [(1,’C’),(3,’O’),(4,’D’),(7,’E’),(9,’M’),(12,’O’),
(14,’T’),(17,’I’)]
I
17s
T
14s
Event Source
Slide 17
Slide 17 text
Wait!
Slide 18
Slide 18 text
Semantically, EventStream is a list,
what if I use...
Slide 19
Slide 19 text
C
1s
Ks O
3s
D E
7s
M
9s
O
12s
4s
Map
f(v) = toLowerCase(v)
c
1s
Ks.map(f) o
3s
d e
7s
m
9s
o
12s
4s
14s
t
14s
T
Slide 20
Slide 20 text
C
1s
Ks O
3s
D E
7s
M
9s
O
12s
4s
Filter
f(v) = return v == ‘o’;
ks.filter(f) o
3s
o
12s
14s
T
Slide 21
Slide 21 text
Es1 1
3s
2
12s
Merge
14s
3
Es2 B C
7s
D
9s
4s
A
1s
Es1.merge(Es2) 1
3s
B C
7s
D
9s
2
12s
4s 14s
3
A
1s
How do I create an EventStream?
● From jQuery/Zepto object:
○ $(‘#mydiv’).asEventStream(‘click’)
● From promise object:
○ Bacon.fromPromise($.ajax(“/search/”+query”))
● From DOM event:
○ Bacon.fromEvent(document.body, ‘click’)
● One-event eventstream:
○ Bacon.once(‘Hello’)
● Interval:
○ Bacon.interval(1000, ‘Tick’)
Slide 26
Slide 26 text
Architecture of an FRP app
Event
Stream
...
Event
Stream
Event
Stream
Merge Model
Transformation
Side
Effects
...
Side
Effects
Side
Effects
Slide 27
Slide 27 text
Simple Up/Down example
Slide 28
Slide 28 text
Simple Up/Down example
Up Click
Stream
Down
Click
Stream
Transform
Merge
Div
Content
Transform
Slide 29
Slide 29 text
Simple Up/Down example
var up = $('#upButton').asEventStream('click');
var down = $('#downButton').asEventStream('click');
var counter = up
.map(1)
.merge(down.map(-1))
.scan(0, (acc, val) => return acc + val;);
counter.assign($('#result'), 'text');
Slide 30
Slide 30 text
Form validation example
Slide 31
Slide 31 text
Name
Keyup
Stream
Min
Keyup
Stream
Merge to
Model
Filter
Valid
Form validation example
Max
Keyup
Stream
Enable
Submit
Show
error
msg
Slide 32
Slide 32 text
Form validation example
// Input streams
var nameStream = $('#name')
.asEventStream('keyup')
.map(event => return event.target.value;)
.skipDuplicates()
.toProperty($('#name').val());
var minStream = $('#min')
.asEventStream('keyup')
.map(event => return parseInt(event.target.value);)
.skipDuplicates()
.toProperty(parseInt($('#min').val()));
Slide 33
Slide 33 text
Form validation example
// Model Stream
var modelStream = Bacon.combineTemplate({
name: nameStream,
min: minStream,
max: maxStream
});
Slide 34
Slide 34 text
Form validation example
//Side effects
evaluateStream.map(m => return !m.valid;)
.assign($('#submitButton'), 'attr', 'disabled');
evaluateStream.map(m => return m.message;)
.assign($('#error'), 'text');
Slide 35
Slide 35 text
Shape designer example
Slide 36
Slide 36 text
Shape
Stream
Color
Stream
Merge to
Model
Transform
Shape designer example
Size
Stream
Canvas
Drawing
Slide 37
Slide 37 text
Shape designer example
// Input streams
var colorStream = $('#color').asEventStream('change')
.map(event => return event.target.value;)
.skipDuplicates()
.toProperty($('#color').val())
.map(c => transformColor(c));
Slide 38
Slide 38 text
Shape designer example
//ModelStream
var modelStream = Bacon.combineTemplate({
shape: shapeStream,
size: sizeStream,
color: colorStream
});
Slide 39
Slide 39 text
Shape designer example
// SideEffects
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
modelStream.onValue(m => {
drawModel(ctx, m);
});
Tweet
Stream
North
Filter
Transform
Twitter Map example (Client)
Merge
South
Filter
Transform
Put
Marker
Write
Tweet
Slide 45
Slide 45 text
var tweetStream = Bacon.fromEvent(socket, 'tweet');
var northStream = tweetStream.filter(inNorth)
.map(t => return t.text + ' (N)';);
var southStream = tweetStream.filter(inSouth)
.map(t => return t.text + ' (S)';);
var finalStream = northStream.merge(southStream);
finalStream.onValue(t => {
putMarker(t);
writeTweet(t);
});
Twitter Map example (Client)
Slide 46
Slide 46 text
Conclusion
Slide 47
Slide 47 text
Advantages
● It allows you to define time-dependent application in a declarative
way.
● Time-varying values are first class citizen.
● It allows you to use a data transformation style using mostly pure
functions.
● Side-effects are confined to one part of the application
Slide 48
Slide 48 text
Problems
● What if one transformation function consumes too much time?
● What if one EventStream is too fast for the system to process?
● What if one EventStream in a zip is way faster than the other one?
Slide 49
Slide 49 text
Implementation
● Pull-based
○ Demand-driven. Sampling of the reactive EventStreams.
● Push-based
○ It can be implemented on top of event loops.
● Infinite vs finite
○ (Bacon.js) Streams are finite: They can start and end at
arbitrary moments.
○ (Elm) Streams are infinite: Stream are always “producing”
values (Hot/Cold).
References, Links and Videos
● Functional Reactive Animation, Conal Elliot et al, 1998
● Push-Pull Functional Reactive Programming, Conal Elliot
● Deprecating the observer pattern, Martin Odersky et al
● React 2014: Erik Meijer - What does it mean to be Reactive?
● “Controlling Time and Space: understanding the many formulations
of FRP” by Evan Czaplicki (Elm creator)
● Ryan Trinkle - Reflex: Practical Functional Reactive Programming
(Haskell)
● Lambda Jam 2014 - Conal Elliot - The Essence and Origins of
Functional Reactive Programming