FRP-intro

An introduction to Functional Reactive Programming

View the Project on GitHub

An Introduction to Functional Reactive Programming

For Mathew Zaleski’s CSC302 (Software Engineering Large Systems) course at the University of Toronto, I created and delivered a set of lectures on Functional Reactive Programming.

The lecture slides are available here. This repo contains the complete code for the demos discussed in the slides.

The content below is intended to be a tutorial version of the lectures.


Demos

FRP-GOL-init A very simple interactive FRP JS implementation of Conway's Game of Life.
(Modeled directly on the Haskell FRP Game of Life from Tikhon Jelvis' talk, A Sensible Intro to FRP.)
FRP-GOL-testable A slightly more complex interactive FRP JS implementation of Conway's Game of Life, structured for improved testability over FRP-GOL-init.
non-FRP-GOL An interactive JS implementation of Conway's Game of Life, without using FRP principles.
FRP-twitter An FRP implementation of Twitter's "Who to follow" suggestions box.
(Based on an example from Andre Staltz's The introduction to Reactive Programming you've been missing.)

All demos use React.js, and all FRP demos use Bacon.js.

FRP-GOL-init / FRP-GOL-testable / non-FRP-GOL contents

app.js
Game of Life logic (world update functions, etc.)
bundle.js
bundled code produced by the compiler
grid.js
React grid component
index.html
main HTML page
index.js
main app logic, combining the Game of Life logic, React grid component, and app interaction implementation
patternsDict.js
dictionary of Game of Life patterns

FRP-twitter contents

How to use this code

Demo Running at
FRP-GOL-init gabriellesc.github.io/FRP-intro/FRP-GOL-init/
FRP-GOL-testable gabriellesc.github.io/FRP-intro/FRP-GOL-testable/
non-FRP-GOL gabriellesc.github.io/FRP-intro/non-FRP-GOL/
FRP-twitter gabriellesc.github.io/FRP-intro/FRP-twitter/

To run any of the demos locally, simply download its main directory and open index.html.

To modify any of the demos, start by running npm install inside its main directory to install the required Node.js modules.
Build a demo after modifying it by running npm run build inside its main directory, or run npm run watch to automatically re-build the demo each time it is modified.

Some modifications may require additional Babel plugins to be installed (see http://babeljs.io/docs/plugins).


Getting Started With Functional Reactive Programming

Conway’s Game of Life

GOL initial state example GOL moving example

Implementing the Game of Life

We need:

We also want:

Game logic

We would like to implement the game logic as a function, which takes a previous game state and produces the next game state.

Moreover, we would like to treat the function as a black box: it doesn’t matter how it is implemented; we can trust that it will correctly produce the next state if we give it the previous state.

game logic black box arch 1

This means that we can produce new states forever if we

game logic black box arch 2

Functional Game Logic

What’s functional about this model?
It has no side effects (interaction with anything outside the model):

stateless terms

What is the advantage of having a functional model? –> Testability

What’s the problem with this code?

function crazyDouble(x) {
    if (new Date.getDay() == 4)    // if today is Wednesday
	    return x*3;
    else
        return x*2;
}

// We'd like to apply crazyDouble to all the elements of a list...

var doubled = []
for (var elem of [1, 2, 3])
    doubled.append(crazyDouble(elem))

How do we test crazyDouble?

Triggering updates

We want to trigger an update (i.e. call our update function)…

non-FRP black box arch

Can we treat clicks and ticks as events, and implement event handlers? –> What are the challenges of this implementation? –> How would we test this implementation?

Can we create an observable object that holds clicks and ticks, subscribe to it, and trigger an update when a click or tick occurs?
(What is the difference between event handling and observer/observable?)

Observer/Observable Design Pattern

(Adapted from https://csc301-fall-2016.github.io/resources/lec6-2–2016-10-25.pdf)

observer/observable diagram

Observer/Observable - Why?

What is reactive programming?

Wikipedia:

…a declarative programming paradigm concerned with data streams and the propagation of change

The Reactive Manifesto:

Reactive Systems are:

  • Responsive: The system responds in a timely manner if at all possible.
  • Resilient: The system stays responsive in the face of failure.
  • Elastic: The system stays responsive under varying workload.
  • Message Driven: Reactive Systems rely on asynchronous message-passing to establish a boundary between components that ensures loose coupling, isolation and location transparency.

Introduction to Reactive Programming:

Reactive programming is programming with asynchronous data streams.

Modeling data as a stream

At the core of any system are values, which exist for some continuous period (eg. variables, pixels, mouse position). We’ll refer to these as “behaviours”.

mouse button value example

But computers don’t operate continuously (in real time).
And we’re not necessarily interested in behaviours at every point in time (eg. do we always care when the user moves the mouse?).
So we want to examine certain behaviours, in a way that doesn’t depend on time.

We can describe specific conditions on a behaviour, which we’ll call “events”.

mouse click event example

Events are discrete (they only occur at specific points in time).

We need a way to model events and have our system handle them…

If we can connect our system to an input stream, then we can add events to the stream as they occur, and our system can react to them as it receives them.

input stream arch

(Notice that our system still has no side effects!)

We don’t model time, because the timing of an event doesn’t matter to our system!

We are only interested in:

What if we have multiple kinds of events (eg. clicks and ticks)?

We can create streams of each of these events - and then we can combine them (or create new kinds of events) using functional patterns.

combined input stream arch


License

Licensed under the MIT License. See LICENSE for more information.