Elm talk bayhac2015

Post on 05-Aug-2015

198 views 0 download

Transcript of 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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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