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

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:
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

Made with Slides.com