Asynchronous Functional Reactive Programming for GUIs
by Evan Czaplicki and Steven Chong
Overview
- Teaser of Elm (the result of the paper)
- Introduction to FRP
- Problems with FRP
- Solutions in Elm
- Results of paper / Benchmark
Elm
-
what: a functional reactive programming (FRP) language
-
goal: simplify creation of responsive graphical user interfaces (GUIs)
- target: web applications (compiles to JavaScript)
Elm
content = flow down [ plainText "Welcome to Elm!"
, image 150 50 "flower.jpg"
, asText (reverse [1..9]) ]
main = container 180 100 middle content
flow : Direction -> [Element] -> Element
container : TODO
FRP?
- functional: pure functional programming paradigms
- reactive: applied to time-varying values (signals)
i = 0
function increment () {
return ++i
}
increment() // 1
increment() // 2
function increment (i) {
return i + 1
}
increment(0) // 1
increment(1) // 2
impure:
pure:
Why FRP?
- explicitly model complex time-dependent relationships in a high-level declarative way
-
time-dependent relationships: e.g. user clicks on button, which causes a server request, which returns data that needs to be displayed.
- declarative: specify what, not how
Signals
- time-varying values ("values that change over time")
- e.g. user interaction, server requests and responses
Signals
- most FRP languages:
- assume that signals change continuously
- → sample input signals as quickly as possible
- → continually recompute the program with the latest values for the signals
- In practice, however:
- many signals change discretely and infrequently
- → constant sampling leads to unnecessary recomputation
Problems with FRP
-
Inefficiencies:
-
Unnecessary Recomputation (resulting from continuous/pull-approach to signals)
-
Global delays (resulting from keeping the global order of events)
- e.g. waiting for server response before accepting user input again
-
Unnecessary Recomputation (resulting from continuous/pull-approach to signals)
Solution in Elm
-
simple types:
- base types
- functions from simple types to simple types
-
signal types:
- "streams of values"
-
not possible: signals of signals
- would require saving full history of values
Solution in Elm
-
Unnecessary Recomputation:
assume discrete events (signals only change when events occur)
→ push approach (global event dispatcher)
main = lift asText Mouse.position
Mouse.position : Signal (Int,Int)
lift : (a -> b) -> Signal a -> Signal b
asText : a -> Element
Solution in Elm
- Global event dispatcher
-
dispatches all events to all signal sources
-
signal sources decide if value changed or not
- if not, return:
-
dispatches all events to all signal sources
noChange v
Solution in Elm
-
Global delays:
allow programmer to specify when something should be executed regardless of the order of events
→ asynchronous execution (async construct)
(inputField, tags) = Input.text "Enter a tag"
getImage tags =
lift (fittedImage 300 200)
(syncGet (lift requestTag tags))
scene input pos img =
flow down [ input, asText pos, img ]
main = lift3 scene inputField
Mouse.position
(async (getImage tags))
Results of paper
- developed Elm
- a practical, asynchronous FRP language
- with focus on easy creation of responsive GUIs
- allowed efficient execution of FRP programs
(push approach)
- introduced Asynchronous FRP
(async construct)
→ Elm simplifies the complicated task of creating responsive and usable graphical user interfaces
Benchmark
Asynchronous Functional Reactive Programming for GUIs
By omnidan
Asynchronous Functional Reactive Programming for GUIs
- 1,634