Model-View-Update-Communicate Session Types meet the Elm - - PowerPoint PPT Presentation

model view update communicate
SMART_READER_LITE
LIVE PREVIEW

Model-View-Update-Communicate Session Types meet the Elm - - PowerPoint PPT Presentation

Model-View-Update-Communicate Session Types meet the Elm Architecture Simon Fowler University of Edinburgh ABCD Final Meeting 19th December 2019 Functional Session Types EqualityClient : ! Int . ! Int . ? Bool . End Session types: Types


slide-1
SLIDE 1

Model-View-Update-Communicate

Session Types meet the Elm Architecture Simon Fowler

University of Edinburgh ABCD Final Meeting 19th December 2019

slide-2
SLIDE 2

Functional Session Types

EqualityClient : !Int.!Int.?Bool.End equalityClient : EqualityClient ⊸ Bool equalityClient(s) ≜ let s = send (5, s) in let s = send (5, s) in let (res, s) = receive s in close s; res → Session types: Types for protocols → Here, interested in linear functional languages → Huge advances over the course of ABCD!

2

slide-3
SLIDE 3

Interactivity? Majority of implementations: Command line applications

Really, communication actions triggered by UI events, sending user-specified data Difficult to embed linear resources into a GUI Some early work on session types + GUIs, but ad-hoc, not formal → (Client code in Exceptional Asynchronous Session Types was a mess)

3

slide-4
SLIDE 4

TwoFactorClient Username Password & Authenticated ClientBody Challenge ChallengeKey Response & Authenticated ClientBody AccessDenied End AccessDenied End

slide-5
SLIDE 5

TwoFactorClient ≜ !(Username, Password).&{ Authenticated : ClientBody, Challenge : ?ChallengeKey.!Response.&{Authenticated : ClientBody, AccessDenied : End}, AccessDenied : End }

slide-6
SLIDE 6

Approach

Step 1: Formalise a GUI framework

→ I chose Model-View-Update, as pioneered by Elm

π

Step 2: Extend formalism with session types

→ Some intricacies...

Step 3: Implement in Links

→ Result: Idiomatic server and client code for session- typed web applications

5

slide-7
SLIDE 7

Contributions λMVU: A Formal Model of the MVU Architecture

→ First formal characterisation of MVU → Soundness proofs

Extending λMVU with Session Types

→ Formal characterisations of subscriptions and commands from Elm → Linearity and model transitions allow safe integration of session types

Implementation and Examples

→ MVU + extensions implemented in Links language → Example applications including two-factor authentication and chat server

6

slide-8
SLIDE 8

Demo: A box and a label

slide-9
SLIDE 9

Model-View-Update

https://www.slideshare.net/RogerioChaves1/introduction-to-elm

Model: State of application View: Renders model as HTML Update: Updates model based on UI messages

7

slide-10
SLIDE 10

Model-View-Update (in Links)

typename Model = (contents: String ); typename Message = [| UpdateBox: String |]; sig view : (Model) ~> HTML(Message) fun view(model) { vdom <input type="text" value="{model.contents}" e:onInput="{fun(str) { UpdateBox(str) }}"/> <div >{ textNode(reverse(model.contents )) }</div > } sig updt : (Message , Model) ~> Model fun updt(UpdateBox(newStr), model) { (contents = newStr) } mvuPage (( contents=""), view , updt)

8

slide-11
SLIDE 11

Model-View-Update (in Links)

typename Model = (contents: String ); typename Message = [| UpdateBox: String |]; sig view : (Model) ~> HTML(Message) fun view(model) { vdom <input type="text" value="{model.contents}" e:onInput="{fun(str) { UpdateBox(str) }}"/> <div >{ textNode(reverse(model.contents )) }</div > } sig updt : (Message , Model) ~> Model fun updt(UpdateBox(newStr), model) { (contents = newStr) } mvuPage (( contents=""), view , updt)

8

slide-12
SLIDE 12

Model-View-Update (in Links)

typename Model = (contents: String ); typename Message = [| UpdateBox: String |]; sig view : (Model) ~> HTML(Message) fun view(model) { vdom <input type="text" value="{model.contents}" e:onInput="{fun(str) { UpdateBox(str) }}"/> <div >{ textNode(reverse(model.contents )) }</div > } sig updt : (Message , Model) ~> Model fun updt(UpdateBox(newStr), model) { (contents = newStr) } mvuPage (( contents=""), view , updt)

8

slide-13
SLIDE 13

Model-View-Update (in Links)

typename Model = (contents: String ); typename Message = [| UpdateBox: String |]; sig view : (Model) ~> HTML(Message) fun view(model) { vdom <input type="text" value="{model.contents}" e:onInput="{fun(str) { UpdateBox(str) }}"/> <div >{ textNode(reverse(model.contents )) }</div > } sig updt : (Message , Model) ~> Model fun updt(UpdateBox(newStr), model) { (contents = newStr) } mvuPage (( contents=""), view , updt)

8

slide-14
SLIDE 14

λMVU: Model-View-Update, Formally

slide-15
SLIDE 15

Syntax

Types A, B, C ::= 1 | A → B | A × B | A + B | String | Int | Html(A) | Attr(A) String literals s Integers n Terms L, M, N ::= x | λx.M | M N | () | s | n | (M, N) | let (x, y) = M in N | inl x | inr x | case L {inl x → M; inr y → N} | htmlTag t M N | htmlText M | htmlEmpty | attr ak M | attrEmpty | M ⋆ N Tag names t Attribute keys ak ::= at | h Attribute names at Event handler names h

9

slide-16
SLIDE 16

Syntactic Sugar

  • html

<input type = "text" value = {model.contents}

  • nInput = {λstr.UpdateBox(str)}></input>

<div>{htmlText (reverseString (model.contents))}</div>

  • =

(htmlTag input ((attr type "text") ⋆ (attr value model.contents)⋆ (attr onInput (λstr.UpdateBox(str)))) htmlEmpty) ⋆ htmlTag div attrEmpty (htmlText reverseString (model.contents))

10

slide-17
SLIDE 17

Semantics by example: Box and a label

model ≜ (contents = "") view ≜ λmodel.html

<input type = "text" value = {model.contents}

  • nInput = {λstr.UpdateBox(str)}></input>

<div>{htmlText (reverseString (model.contents))}</div>

update ≜ λUpdateBox(str).(contents = str)

11

slide-18
SLIDE 18

Semantics by example: Box and a label

run model view update

12

slide-19
SLIDE 19

Semantics by example: Box and a label

(model, view model) | (view, update) | ϵ htmlEmpty

12

slide-20
SLIDE 20

Semantics by example: Box and a label

(model,

<input type = "text" value = ""

  • nInput = {λstr.UpdateBox(str)}>

</input> <div></div>

) | (view, update) | ϵ htmlEmpty

12

slide-21
SLIDE 21

Semantics by example: Box and a label

idle model | (view, update) | ϵ

<input type = "text" value = ""

  • nInput = {λstr.UpdateBox(str)} @ ϵ></input>

<div @ ϵ></div>

12

slide-22
SLIDE 22

Semantics by example: Box and a label

idle model | (view, update) | ϵ

<input type = "text" value = ""

  • nInput = {λstr.UpdateBox(str)} @ click(())·

keyDown(75) · keyUp(75) · input("k")></input>

<div @ ϵ></div>

12

slide-23
SLIDE 23

Semantics by example: Box and a label

idle model | (view, update) | ϵ

<input type = "text" value = ""

  • nInput = {λstr.UpdateBox(str)} @ input("k")>

</input> <div @ ϵ></div>

12

slide-24
SLIDE 24

Semantics by example: Box and a label

idle model | (view, update) | ϵ ( (UpdateBox("k")) )

<input type = "text" value = ""

  • nInput = {λstr.UpdateBox(str)}

@ ϵ></input>

<div @ ϵ></div>

12

slide-25
SLIDE 25

Semantics by example: Box and a label

idle model | (view, update) | UpdateBox("k")

<input type = "text" value = ""

  • nInput = {λstr.UpdateBox(str)}

@ ϵ></input>

<div @ ϵ></div>

12

slide-26
SLIDE 26

Semantics by example: Box and a label

handle(model, (view, update), UpdateBox("k")) | (view, update) | ϵ

<input type = "text" value = ""

  • nInput = {λstr.UpdateBox(str)}

@ ϵ></input>

<div @ ϵ></div>

(where handle(m, (v, u), msg) ≜ let m′ = u (msg, m) in (m′, v m′))

12

slide-27
SLIDE 27

Semantics by example: Box and a label

( (contents = ”k”),

<input type = "text" value = "k"

  • nInput = {λstr.UpdateBox(str)}>

</input> <div>k</div>

) | (view, update) | ϵ

<input type = "text" value = ""

  • nInput = {λstr.UpdateBox(str)}

@ ϵ></input>

<div @ ϵ></div>

12

slide-28
SLIDE 28

Semantics by example: Box and a label

idle (contents = "k") | (view, update) | ϵ

<input type = "text" value = "k"

  • nInput = {λstr.UpdateBox(str)} @ ϵ></input>

<div @ ϵ>k</div>

12

slide-29
SLIDE 29

Metatheory

Theorem (Preservation)

If Γ ⊢ C and C − → C′, then Γ ⊢ C′.

Theorem (Event Progress)

If · ⊢ C, either: → there exists some C′ such that C − →E C′; or → C = idle Vm | (Vv, Vu) | ϵ D where D cannot be written D[htmlTag−

→ e t V W]

for some non-empty − → e .

13

slide-30
SLIDE 30

Extending λMVU

slide-31
SLIDE 31

Commands

Commands: Allow side effects to be performed by event loop Example: Asynchronous naïve Fibonacci

Model Maybe Int Message StartComputation Result Int view Model Html Message view model html case model Just result htmlText intToString x Nothing htmlText "Waiting …"

<button onClick

StartComputation >Start!< button> update Message Model Model Cmd Message update msg model case msg StartComputation Nothing cmdSpawn Result naïveFib Result x Just x cmdEmpty

14

slide-32
SLIDE 32

Commands

Commands: Allow side effects to be performed by event loop Example: Asynchronous naïve Fibonacci

Model ≜ Maybe(Int) Message ≜ StartComputation | Result(Int) view Model Html Message view model html case model Just result htmlText intToString x Nothing htmlText "Waiting …"

<button onClick

StartComputation >Start!< button> update Message Model Model Cmd Message update msg model case msg StartComputation Nothing cmdSpawn Result naïveFib Result x Just x cmdEmpty

14

slide-33
SLIDE 33

Commands

Commands: Allow side effects to be performed by event loop Example: Asynchronous naïve Fibonacci

Model ≜ Maybe(Int) Message ≜ StartComputation | Result(Int) view : Model → Html(Message) view = λmodel.html {case model { Just(result) → htmlText intToString(x); Nothing → htmlText "Waiting …" } }

<button onClick = {λ().StartComputation}>Start!</button>

update Message Model Model Cmd Message update msg model case msg StartComputation Nothing cmdSpawn Result naïveFib Result x Just x cmdEmpty

14

slide-34
SLIDE 34

Commands

Commands: Allow side effects to be performed by event loop Example: Asynchronous naïve Fibonacci

Model ≜ Maybe(Int) Message ≜ StartComputation | Result(Int) view : Model → Html(Message) view = λmodel.html {case model { Just(result) → htmlText intToString(x); Nothing → htmlText "Waiting …" } }

<button onClick = {λ().StartComputation}>Start!</button>

update : (Message × Model) → (Model, Cmd(Message)) update = λ(msg, model). case msg { StartComputation → (Nothing, cmdSpawn Result(naïveFib(1000))) Result(x) → (Just(x), cmdEmpty) }

14

slide-35
SLIDE 35

Linearity

Stock λMVU does not support linearity (as m′ is used non-linearly when calculating new model and view): handle(m, (v, u), msg) ≜ let m′ = u m in (m′, v m′) → Idea: linear parts of model only used in update, not view. Extract unrestricted part of the model: extract : Model → (Model × UnrestrictedModel) view : UnrestrictedModel → Html(Message) handle(m, (v, u, e), msg) ≜ let m′ = u (msg, m) in let (m′, unrM) = e m′ in (m′, v unrM)

15

slide-36
SLIDE 36

Demo: PingPong application

slide-37
SLIDE 37

PingPong in λMVU

PingPong ≜ µt.!Ping.?Pong.t Model ≜ Pinging(PingPong) | Waiting Message ≜ Click | Ponged(PingPong) update ≜ λ(msg, model). case msg { Click → handleClick(model) Ponged(c) → handlePonged(model, c) } handleClick(model) ≜ case model { Pinging(c) → let c = send (Ping, c) in let cmd = cmdSpawn (let (pong, c) = receive c in Ponged(c)) in (Waiting, cmd) Waiting → (Waiting, cmdEmpty) } handlePonged(model, c) ≜ case model { Pinging(c′) → cancel c′; (Pinging(c), cmdEmpty) Waiting → (Pinging(c), cmdEmpty) }

16

slide-38
SLIDE 38

PingPong in λMVU

PingPong ≜ µt.!Ping.?Pong.t Model ≜ Pinging(PingPong) | Waiting Message ≜ Click | Ponged(PingPong) update ≜ λ(msg, model). case msg { Click → handleClick(model) Ponged(c) → handlePonged(model, c) } handleClick(model) ≜ case model { Pinging(c) → let c = send (Ping, c) in let cmd = cmdSpawn (let (pong, c) = receive c in Ponged(c)) in (Waiting, cmd) Waiting → (Waiting, cmdEmpty) } handlePonged(model, c) ≜ case model { Pinging(c′) → cancel c′; (Pinging(c), cmdEmpty) Waiting → (Pinging(c), cmdEmpty) }

16

slide-39
SLIDE 39

Illegal states

Issue

→ Must handle messages impossible in a given state (e.g., receiving a pong while waiting to send a ping) → Problem: models treated as sum types

Proposal

→ Multiple model types, transitions between them → Make illegal states unrepresentable!

17

slide-40
SLIDE 40

Model transitions

Waiting state WModel ≜ Waiting WUModel ≜ 1 WMessage ≜ Ponged(c) wView ≜ λ(). html

<button disabled = "true">

Send Ping!

</button>

wUpdate ≜ λ(Ponged(c), Waiting). transition Pinging(c) pView pUpdate pExtract cmdEmpty wExtract ≜ λx.(Waiting, ()) Pinging state PModel ≜ Pinging(PingPong) PUModel ≜ 1 PMessage ≜ Click pView ≜ λ(). html

<button onClick = {λ().Click}>

Send Ping!

</button>

pUpdate ≜ λ(Click, Pinging(c)). let c = send (Ping, c) in let cmd = cmdSpawn (let (pong, c) = receive c in Ponged(c)) in transition () wView wUpdate wExtract cmd pExtract ≜ λc.(c, ())

18

slide-41
SLIDE 41

Model transitions

Waiting state WModel ≜ Waiting WUModel ≜ 1 WMessage ≜ Ponged(c) wView ≜ λ(). html

<button disabled = "true">

Send Ping!

</button>

wUpdate ≜ λ(Ponged(c), Waiting). transition Pinging(c) pView pUpdate pExtract cmdEmpty wExtract ≜ λx.(Waiting, ()) Pinging state PModel ≜ Pinging(PingPong) PUModel ≜ 1 PMessage ≜ Click pView ≜ λ(). html

<button onClick = {λ().Click}>

Send Ping!

</button>

pUpdate ≜ λ(Click, Pinging(c)). let c = send (Ping, c) in let cmd = cmdSpawn (let (pong, c) = receive c in Ponged(c)) in transition () wView wUpdate wExtract cmd pExtract ≜ λc.(c, ())

18

slide-42
SLIDE 42

Wrapping up

slide-43
SLIDE 43

Conclusion

Summary

→ First formal characterisation of MVU architecture → First formal integration of session-typed communication and GUI programming → Not only Greek: fully implemented in Links, along with examples

Find out more!

→ Draft paper: http://bit.ly/mvu-arxiv → Artifact: http://bit.ly/mvu-artifact @Simon_JF simon.fowler@ed.ac.uk http://www.links-lang.org

  • pam install links

19