Zen-like State Management with FRP

Chalmers, April 2014

Stian Veum Møllersen / @mollerse

open.bekk.no

Hi, my name is Stian

I'm a frontender

To tackle complexity

That's my job

We are taking lessons from the past

But we are forgetful

Functional programming

Programming with functions

But wait, there's more!

Immutable data

Nothing ever changes

Pure functions

Functions that doesn't do anything

How does this apply to real programs?

Abstractions

User interfaces

Attributes of user interfaces

Global mutable state

Attributes of user interfaces

Asynchronous actions

Attributes of user interfaces

Temporally dependent actions

Attributes of user interfaces

Dependencies between data

What do we need to do in order to use functional programming principles?

  • Abstract state mutation
  • Declarative dependencies between pieces of state
  • Perserve temporal information

Reactive programming

A programming paradigme oriented around data flows and propagation of changes to state.

Data flow programming

Spreadsheets

Values and formulae

How to think in data flow

Reactive datatypes

The primary abstraction

How does reactive programming solve the problem with user interfaces?

Abstract state mutation

The reactive datatypes delegate all state mutation to the underlying execution model

Declarative dependencies between pieces of state

Higher order reactive datatypes

Perserve temporal information

Perserve temporal information

Save the time information connected to a change in state

Continous and discrete

f(t) => v og [(v, t)]

Functional & Reactive

EventStream & Behavior

Primary abstractions for discrete and continous values

Combinators and functors

Compositional vocabulary from functional programming

We are still mutating the state at the borders of the graph.

What do we achieve?

Functional reasoning despite unfit domain

FRP in practice: Implementations

Implementations of FRP

Haskell and friends

Implementations of FRP

Web and JavaScript

  • RxJS
  • Elm
  • Flapjax
  • Bacon.js

FRP in practice: Bacon.js

Sources

  • fromEventTarget
  • fromPromise
  • constant
  • and more

Sinks

onValue

Composition

  • map
  • filter
  • reduce
  • merge
  • and many more

Low level

Only the important bits

Example: One-directional binding

Goal: Text in inputfield is replicated in label

var input = Bacon.fromEventTarget(document.querySelector("#text", 'keyup')
var value = input.map(el => el.value)
value.onValue(v => document.querySelector('label').innerHTML = v);

Demo

Example: WebSockets and multiple clients.

We are making a simple voting system based on WebSockets.

What we need to do

  • Connect and receive data from a WebSocket.
  • Count the votes.
  • Calculate the percentage each alternative gets.
  • Reflect the percentage in the interface.
var socketStream = Bacon.fromEventTarget(socket, "vote");
var totalVoteProperty = function (id) {
  return socketStream
    .filter(isId(id))
    .map(1)
    .scan(0, add);
};
var percentage = function (numVotes, total) {
  return numVotes
    .combine(total, _toPercentage);
};
var sum = socketStream.map(1).scan(0, _add);
["alt1", "alt2", "alt3"].forEach(function (id) {
  return percentage(totalVoteProperty(id), sum)
  .onValue(v => document.querySelector('#'+id).value = v);
});

How do you spell banana in swedish?

Vote at: http://frp.herokuapp.com

Wrap up

Managing complexity is hard

But functional programming makes it easier

User interfaces are tricky

But reactive programming make them manageable

Combinine functional and reactive programming for a plesant way of managing complexity in user interfaces

Questions, feedback and other things

@mollerse

stian.veum.mollersen@bekk.no

Thank you for having me!