Elm talk bayhac2015

26
Functional Reactive Programming and Elm Sergei Winitzki BayHac 2015 June 14, 2015 Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 1 / 26

Transcript of Elm talk bayhac2015

Page 1: Elm talk bayhac2015

Functional Reactive Programming and Elm

Sergei Winitzki

BayHac 2015

June 14, 2015

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 1 / 26

Page 2: Elm talk bayhac2015

Part 1. Functional reactive programming and Elm

FRP has little to do with...multithreading, message-passing concurrency, “actors”distributed computing on massively parallel, load-balanced clustersmap/reduce, “reactive extensions”, the “reactive manifesto”

FRP means (in my definition)...pure functions using temporal types as primitives

I (temporal type ≈ lazy stream of values)

FRP is probably most useful for:GUI and event-driven programming

Elm is...a viable implementation of FRP geared for Web GUI apps

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 2 / 26

Page 3: Elm talk bayhac2015

Difficulties in reactive programming

Imperative implementation is one problem among many...Input signals may come at unpredictable times

I Imperative updates are difficult to keep in the correct orderI Flow of events becomes difficult to understand

Asynchronous (out-of-order) callback logic becomes opaqueI “callback hell”: deeply nested callbacks, all mutating data

Inverted control (“the system will call you”) obscures the flow of dataSome concurrency is usually required (e.g. background tasks)

I Explicit multithreaded code is hard to write and debug

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 3 / 26

Page 4: Elm talk bayhac2015

FRP basics

Reactive programs work on infinite streams of input/output valuesMain idea: make streams implicit, as a new “temporal” type

I Σα — an infinite stream of values of type αI alternatively, Σα is a value of type α that “changes with time”

Reactive programs are viewed as pure functionsI a GUI is a pure function of type Σ Inputs → Σ ViewI a Web server is a pure function Σ Request → Σ ResponseI all mutation is implicit in the program

F instead of updating an x:Int, we define a value of type Σ IntF our code is 100% immutable, no side effects, no IO monads

I asynchronous behavior is implicit: our code has no callbacksI concurrency / parallelism is implicit

F the FRP runtime will provide the required scheduling of events

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 4 / 26

Page 5: Elm talk bayhac2015

Czaplicki’s (2012) core Elm in a nutshell

Elm is a pure polymorphic λ-calculus with products and sumsTemporal type Σα — a lazy sequence of values of type αTemporal combinators in core Elm:

constant: α→ Σαmap2: (α→ β → γ)→ Σα→ Σβ → Σγscan: (α→ β → β)→ β → Σα→ Σβ

No nested temporal types: constant (constant x) is ill-typed!Domain-specific primitive types: Bool, Int, Float, String, ViewStandard library with data structures, HTML, HTTP, JSON, ...

I ...and signals Time.every, Mouse.position, Window.dimensions, ...I ...and some utility functions: map, merge, drop, sampleOn, ...

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 5 / 26

Page 6: Elm talk bayhac2015

Details: Elm type judgments [Czaplicki 2012]

Polymorphically typed λ-calculus (also with temporal types)

Γ, (x : α) ` e : β

Γ ` (λx .e) : α→ βLambda

Γ ` e1 : α→ β Γ ` e2 : α

Γ ` (e1 e2) : βApply

Temporal types are denoted by Στ

I In these rules, type variables α, β, γ cannot involve Σ:

Γ ` e : α

Γ ` (constant e) : ΣαConst

Γ ` m : α→ β → γ Γ ` p : Σα Γ ` q : Σβ

Γ ` (map2m p q) : ΣγMap2

Γ ` u : α→ β → β Γ ` e : β Γ ` q : Σα

Γ ` (scan u e q) : ΣβScan

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 6 / 26

Page 7: Elm talk bayhac2015

Elm operational semantics 0: Current values

An Elm program is a temporal expression of type ...→ ΣViewI Temporal expressions are built from input signals and combinatorsI It is not possible to “consume” a signal (Σα→ β)I A value of type ΣΣα is impossible in a well-typed expression

Every temporal expression has a current value denoted by e [c]

Γ ` e : Σα Γ ` c : α

Γ ` e [c] : ΣαCurVal

Some current values are “freshly updated” while others are “stale”I Denote a fresh value by asterisk: e [c]

I In Elm, current values are implemented with an Either type

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 7 / 26

Page 8: Elm talk bayhac2015

Elm operational semantics 1: Initial values

Every temporal expression has an initial (stale) current valueEvery predefined input signal i : Σα, i ∈ I has an initial value: i [a]

Initial current values for all expressions are derived:

Γ ` (constant c) : Σα

Γ ` (constant c)[c] : ΣαConstInit

Γ `(map2 m p[a] q[b]

): Σγ

Γ ` (map2 m p q)[m a b] : ΣγMap2Init

Γ ` (scan u e q) : Σβ

Γ ` (scan u e q) [e] : ΣβScanInit

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 8 / 26

Page 9: Elm talk bayhac2015

Elm operational semantics 2: Updating signals

Update steps happen only to input signals s ∈ I and one at a timeUpdate steps Us←a {...} are applied to the whole program at once:

Γ ` s : Σα s ∈ I Γ ` a : α Γ ` e [c] : Σβ Γ ` c ′ : β

Γ ` Us←a

{e [c]}⇒ e [c ′]

An update step on s will leave all other input signals unchanged:

∀s 6= s ′ ∈ I : Us←b

{s [a]}⇒ s [b]

∗Us←b

{s ′[c]}⇒ s ′[c]

Elm has an efficient implementation:I The instances of input signals within expressions are not duplicatedI Stale current values are cached and not recomputed

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 9 / 26

Page 10: Elm talk bayhac2015

Elm operational semantics 3: Updating combinators

Operational semantics does not reduce temporal expressions:I The whole program remains a static temporal expression treeI Only the current values are updated in subexpressions"

Us←a

{(constant c)[c]

}⇒ (constant c)[c] ConstUpd

Us←a {map2 m p q}

⇒(map2 m Us←a {p}[v ] Us←a {q}[w ]

)[m v w ]

Map2Upd

Us←a

{(scan u e q)[b]

}⇒(scan u e Us←a {q}[c]

∗)[u c b]∗ ScanPUpd

All computations during an update step are synchronousI The expression Us←b

{e [c]}is reduced after all subexpressions of e

I Current values are non-temporal and are evaluated eagerlyI map2 updates whenever one of its subexpressions updateI scan updates only if its subexpression is freshly updated

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 10 / 26

Page 11: Elm talk bayhac2015

GUI building: “Hello, world” in Elm

The value called main will be visualized by the runtime

import Graphics.Element (..)import Text (..)import Signal (..)

text : Elementtext = plainText "Hello, World!"

main : Signal Elementmain = constant text

Try Elm online at http://elm-lang.org/try

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 11 / 26

Page 12: Elm talk bayhac2015

Example of using scan

Specification:I I work only after the boss comes by and unless the phone rings

Implementation:

after_unless : (Bool, Bool) -> Bool -> Boolafter_unless (b,p) w = (w || b) && not p

boss_and_phone : Signal (Bool,Bool)

i_work : Signal Booli_work = scan after_unless False (boss_and_phone)

Demo (boss_phone_work.elm)

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 12 / 26

Page 13: Elm talk bayhac2015

Typical GUI boilerplate in Elm

A state machine with stepwise update:

update : Command → State → State

A rendering function (View is either Element or Html):

draw : State → View

A manager that merges the required input signals into one:I may use Mouse, Keyboard, Time, HTML stuff, etc.

merge_inputs : Signal Command

Main boilerplate:

init_state : Statemain : Signal Viewmain = map draw (scan update init_state merge_inputs)

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 13 / 26

Page 14: Elm talk bayhac2015

Some limitations of Elm-style FRP

No higher-order signals: Σ(Σα) is disallowed by the type systemNo distinction between continuous time and discrete timeThe signal processing logic is fully specified staticallyNo constructors for user-defined signalsNo recursion possible in signal definition!

I Awkward mechanisms for “tying the knot” in Elm

No full concurrency (e.g. “dining philosophers”)

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 14 / 26

Page 15: Elm talk bayhac2015

Elm-style FRP: the good parts

Transparent, declarative modeling of data through ADTsImmutable and safe data structures (Array, Dict, ...)No runtime errors or exceptions!Space/time leaks are impossible!Language is Haskell-like but simpler for beginnersFull type inferenceEasy deployment and interop in Web applicationsGood support for HTML/CSS, HTTP requests, JSONGood performance of caching HTML viewsSupport for Canvas and HTML-free UI building

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 15 / 26

Page 16: Elm talk bayhac2015

Part 2. Temporal logic and FRP

Reminder (Curry-Howard): logical expressions will be typesI ...and the axioms will be primitive terms

We only need to control the order of events: no “hard real-time”How to understand temporal logic:

I classical propositional logic ≈ Boolean arithmeticI intuitionistic propositional logic ≈ same but without true / false

dichotomyI (linear-time) temporal logic LTL≈ Boolean arithmetic for infinite

sequencesI intuitionistic temporal logic ITL≈ same but without true / false

dichotomy

In other words:I an ITL type represents a single infinite sequence of values

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 16 / 26

Page 17: Elm talk bayhac2015

Boolean arithmetic: notation

Classical propositional (Boolean) logic: T , F , a ∨ b, a ∧ b, ¬a, a→ b

A notation better adapted to school-level arithmetic: 1, 0, a+b, ab, a′

The only “new rule” is 1 + 1 = 1Define a→ b = a′ + b

Some identities:

0a = 0, 1a = a, a + 0 = a, a + 1 = 1,a + a = a, aa = a, a + a′ = 1, aa′ = 0,

(a + b)′ = a′b′, (ab)′ = a′ + b′,(a′)′

= a

a (b + c) = ab + ac , (a + b) (a + c) = a + bc

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 17 / 26

Page 18: Elm talk bayhac2015

Boolean arithmetic: example

Of the three suspects A, B , C , only one is guilty of a crime.Suspect A says: “B did it”. Suspect B says: “C is innocent.”The guilty one is lying, the innocent ones tell the truth.

φ =(ab′c ′ + a′bc ′ + a′b′c

) (a′b + ab′

) (b′c ′ + bc

)Simplify: expand the brackets, omit aa′, bb′, cc ′, replace aa = a etc.:

φ = ab′c ′ + 0 + 0 = ab′c ′

The guilty one is A.

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 18 / 26

Page 19: Elm talk bayhac2015

Propositional linear-time temporal logic (LTL)

We work with infinite boolean sequences (“linear time”)Boolean operations:

a = [a0, a1, a2, ...] ; b = [b0, b1, b2, ...] ;

a + b = [a0 + b0, a1 + b1, ...] ; a′ =[a′0, a

′1, ...

]; ab = [a0b0, a1b1, ...]

Temporal operations:

(Next) Na = [a1, a2, ...]

(Sometimes) Fa = [a0 + a1 + a2 + ..., a1 + a2 + ..., ...]

(Always) Ga = [a0a1a2a3..., a1a2a3..., a2a3..., ...]

Other notation (from modal logic):

Na ≡ ©a; Fa ≡ ♦a; Ga ≡ �a

Weak Until: pUq = “p holds from now on until q first becomes true”

pUq = q + pN (q + pN (q + ...))

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 19 / 26

Page 20: Elm talk bayhac2015

LTL: temporal specification

Whenever the boss comes by my office, I will start working.Once I start working, I will keep working until the telephone rings.

G ((b → Fw) (w → wUr)) = G((b′ + Fw

) (w ′ + wUr

))Whenever the button is pressed, the dialog will appear.The dialog will disappear after 1 minute of user inactivity.

G((b → Fd) (d → Ft)

(d → dUtd ′

))The timer t is an external event and is not specified hereDifficult to say “x stays true until further notice”

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 20 / 26

Page 21: Elm talk bayhac2015

Temporal logic redux

Designers of FRP languages must face some choices:LTL as type theory: do we use Nα, Fα, Gα as new types?Are they to be functors, monads, ...?Which temporal axioms to use as language primitives?What is the operational semantics? (I.e., how to compile this?)

A sophisticated example: [Krishnaswamy 2013]uses full LTL with higher-order temporal types and fixpointsuses linear types to control space/time leaks

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 21 / 26

Page 22: Elm talk bayhac2015

Interpreting values typed by LTL

What does it mean to have a value x of type, say, G(α→ αUβ) ??I x : Nα means that x : α will be available only at the next time tick

(x is a deferred value of type α)I x : Fα means that x : α will be available at some future tick(s)

(x is an event of type α)I x : Gα means that a (different) value x : α is available at every tick

(x is an infinite stream of type α)I x : αUβ means a finite stream of α that may end with a β

Some temporal axioms of intuitionistic LTL:

(deferred apply) N (α→ β)→ (Nα→ Nβ) ;

(streamed apply) G (α→ β)→ (Gα→ Gβ) ;

(generate a stream) G (α→ Nα)→ (α→ Gα) ;

(read infinite stream) Gα→ αN(Gα)

(read finite stream) αUβ → β + αN(αUβ)

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 22 / 26

Page 23: Elm talk bayhac2015

Elm as an FRP language

λ-calculus with type Gα, primitives constant, map2, scan

map2 : (α→ β → γ)→ Gα→ Gβ → Gγscan : (α→ β → β)→ β → Gα→ Gβconstant : α→ Gα

(map2 makes G an applicative functor)Limitations:

I Cannot have a type G(Gα), also not using N or FI Cannot construct temporal values by handI This language is an incomplete Curry-Howard image of LTL!

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 23 / 26

Page 24: Elm talk bayhac2015

Conclusions

There are some languages that implement FRP in various ad hoc waysThe ideal is not (yet) reachedElm-style FRP is a promising step in the right direction

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 24 / 26

Page 25: Elm talk bayhac2015

Abstract

In my day job, most bugs come from implementing reactive programsimperatively. FRP is a declarative approach that promises to solve theseproblems.

FRP can be defined as a λ-calculus that admits temporal types, i.e. typesgiven by a propositional intuitionistic linear-time temporal logic (LTL).Although the Elm language uses only a subset of LTL, it achieves highexpressivity for GUI programming. I will formally define the operationalsemantics of Elm. I discuss the advantages and the current limitations ofElm. I also review the connections between temporal logic, FRP, and Elm.

My talk will be understandable to anyone familiar with Curry-Howard andfunctional programming. The first part of the talk is a self-containedpresentation of Elm that does not rely on temporal logic or Curry-Howard.The second part of the talk will explain the basic intuitions behindtemporal logic and its connection with FRP.

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 25 / 26

Page 26: Elm talk bayhac2015

Suggested reading

E. Czaplicki, S. Chong. Asynchronous FRP for GUIs. (2013)E. Czaplicki. Concurrent FRP for functional GUI (2012).N. R. Krishnaswamy.https://www.mpi-sws.org/∼neelk/simple-frp.pdfHigher-order functionalreactive programming without spacetime leaks(2013).M. F. Dam. Lectures on temporal logic. Slides: Syntax and semantics ofLTL, A Hilbert-style proof system for LTLE. Bainomugisha, et al. A survey of reactive programming (2013).W. Jeltsch. Temporal logic with Until, Functional Reactive Programmingwith processes, and concrete process categories. (2013).A. Jeffrey. LTL types FRP. (2012).D. Marchignoli. Natural deduction systems for temporal logic. (2002). –See Chapter 2 for a natural deduction system for modal and temporallogics.

Sergei Winitzki (Versal Group Inc.) FRP and Elm June 14, 2015 26 / 26