at Progscon - London - 22/04/2016
by @doppioslash
Elm:
Finding the Functional in
Reactive Programming
Hi, I'm
Claudia Doppioslash
@doppioslash
Functional Programmer
GameDev
&
I write
www.lambdacat.com
A site about Functional Programming: Elm, Clojure, Idris, etc.
@lambdacat
What is Functional Reactive Programming?
What is Functional Reactive Programming?
Good question!
What is Functional Reactive Programming?
It's a bit like the Boggart Wardrobe
Can't be sure what will come out
What is Functional Reactive Programming?
Jokes aside...
There are many version of FRP, with different implementation trade-offs
The FRP "specs" (denotational semantics) are in PL Theory Terms
What is Functional Reactive Programming?
At least 3 points of view today:
Elm's
Conal's
(the original)
Reactive
Programming's
What is Functional Reactive Programming?
Conal Elliot defined FRP back in 1998, in his paper
"Functional Reactive Animation"
and has kept working on it since then
Official FRP
can be combined with OOP/Imperative/FP
is paradigm on its own
What is Functional Reactive Programming?
Reactive Programming
What is Functional Reactive Programming?
Let's start from RP and get to FRP by fixing RP's problems
What is Functional Reactive Programming?
What is Reactive Programming
What is Reactive Programming
Typical problem that can benefit from RP:
You need to change <something>,
or multiple somethings
when
a button is pressed/
a variable changed/
an event happens/
etc
- Listener
- Observer
- Callback
- ...
What is Reactive Programming
How to do that?
Many names for the same underlying concept
What is Reactive Programming
What is Reactive Programming
Did you deregister your listener?
...or it will go on listening forever.
What is Reactive Programming
Problems
Unpredictable order
Missed first event
Callbacks pyramids
Threading issues
Leaking Callbacks
Accidental Recursion
Ref: FRP Manning book
(depends on listener ordering)
(initialisation order problem)
What is Reactive Programming
When your program is mainly
event-based
a control-flow based paradigm litters observer code everywhere
Examples: Games, UIs
What is Reactive Programming
Your variables/events are better described as Signals
What is Reactive Programming
Your program is then is better described as a Dataflow Graph
What is Reactive Programming
You're explicitely describing the dependencies and not control flow
What you really care about are your events and variables changes, not the control flow
from one-by-one callback/listeners to dependency graph
A matter of perspective...
imperative perspective : explicit ordering
reactive perspective : explicit dependencies
What is Reactive Programming
imperative perspective : sequence
reactive perspective : dependency
What is Reactive Programming
Signals (aka Cells, Events, Behaviour)
- a different way of thinking about variables
- an explicit model of variable mutation in time
What is Reactive Programming
Signals Transformation
-
Filter
-
Merge
-
Apply
What is Reactive Programming
- init, build the graph
- run data through the graph
Running
instead of your custom control flow
What is Reactive Programming
What about those problems?
-
Unpredictable order
-
Missed first event -
Callbacks pyramids -
Threading issues (a bit)
-
Leaking Callbacks -
Accidental Recursion
What is Reactive Programming
An Implementation:
"Rx = Observables + LINQ + Schedulers"
What is Reactive Programming
What does RP lack compared to FRP?
To Functional Reactive Programming
To Functional Reactive Programming
- compositionality
- immutability guarantees
- inherently parallelisable
FRP adds to RP:
To Functional Reactive Programming
Referential Transparency
a function when it gets the same inputs, will always return the same output.
To Functional Reactive Programming
What breaks Referential Transparency?
• I/O
• throw any exceptions handled outside of the function
• reading the value of any mutable external variable
• mutate any externally visible state
• keeping state around between invocations of the function
To Functional Reactive Programming
What breaks Referential Transparency?
Basically no Side Effects allowed:
- must not influenced by anything outside the function
- only effect on the outside is the return value
To Functional Reactive Programming
Immutability
Signals are a way to express mutability in a controlled way
Any shared mutable state makes the program harder to parallelise
Compositionality
The property that the meaning of an expression is determined by the meanings of its parts and the rules used to combine them.
Yes, I know.
To Functional Reactive Programming
Compositionality
Being able to compose functions:
add : Int -> Int add n1 = n1 + 2 mult : Int -> Int mult n1 = n1 * 2 composedFunction = add >> multiply > composedFunction 4 12 : number
Let's try again...
To Functional Reactive Programming
In practice...
To Functional Reactive Programming
Let's look at Elm's implementation
What is Elm
(and why you should use it)
What is Elm
FRP-only language:
easier way to get started with FRP
What is Elm
Purely Functional
(Referential Transparency & Immutability)
Eager Evaluation
(not lazy like Haskell)
Static Type System
(similar to Haskell)
What is Elm
Compiles to fast Javascript, HTML, CSS
Interoperates with Javascript while still being type safe
Small
What is Elm
What is Elm
Invented by Evan Czaplicki for his thesis
Meant to be approachable and practical
No 'scary' terms like Monad
What is Elm
In production at:
Practical Elm + Examples
Practical Elm + Examples
Type signatures
add : Int -> Int
Is the signature of a function that takes an Integer and returns an Integer.
add : Int -> Int -> Int
Is the signature of a function that takes two Integers and returns an Integer.
Practical Elm + Examples
Currying
If you partially apply a function, by giving it less arguments than it takes, it will return a function that takes the remaining args:
add : Int -> Int -> Int
add n1 n2 = n1 + n2 > addTen = add 10 <function> : Int -> Int > addTen 1 11 : number
Practical Elm + Examples
Main function
The main function is the entry point of program execution, so you need one, or your code won't run.
It is wired to one or more Signals that drive the whole application.
Practical Elm + Examples
What kind of functions can we apply on signals?
Practical Elm + Examples
For RP we said:
-
Filter
-
Merge
-
Apply
Practical Elm + Examples
map : (a -> result) ->
Signal a ->
Signal result
applies a function on a signal
returns another, transformed, signal
Practical Elm + Examples
filter : (a -> Bool) ->
a ->
Signal a ->
Signal a
Filters out some updates according to a predicate function
Practical Elm + Examples
What is a foldp?
Practical Elm + Examples
A fold from the past
(Similar to Map, a Fold reduces, say, a List to one value, by applying a function to the entries)
Practical Elm + Examples
( Update function )
( default value )
(inputs Signal)
makes a signal that depends on the past values of a signal
(next program state signal)
Practical Elm + Examples
Practical Elm + Examples
Practical Elm + Examples
How to structure programs functionally in Elm
The Functional Triforce
Union Types
Pattern
Matching
Maybe
Union Types
define the Model:
type Tile
= Door Size
| Column
| BackGround BackGroundTile
| Shadow ShadowTile
The Functional Triforce
Maybe
gets rid of NULL errors
type Maybe a
= Just a
| Nothing
The Functional Triforce
Pattern Matching
case maybeVar of Just a -> a Nothing -> "default value"
Much more than Switch Case
The Functional Triforce
Elm is opinionated
How to structure programs
Action Model init : (Model, Effects Action) update : Action -> Model -> (Model, Effects Action) view : Signal.Address Action -> Model -> Html
(Union Type)
How to structure programs
(often a Record (similar to js object))
Update generates the next state of the program by
pattern matching on Actions
using a Model defined
using Union Types and Records
View renders that next state
How to structure programs
Time Travelling Debugger
Time Travelling Debugger
Inspired by
'Inventing on Principle'
Fundamentals made in a few days by Laszlo
Elm's language design is accidentally 'compatible'
Time Travelling Debugger
Demo
Time Travelling Debugger
Records Input Signals
Reapplies functions to inputs
snapshotting for performance
previous state
+
previous inputs=
next state
Time Travelling Debugger
Applying the same inputs will return the same output
(referential transparency)
Time Travelling Debugger
No side effects = can replay code
All mutable state is stored in the foldp
Time Travelling Debugger
Static signal graph
Way to Elm
Way to Elm
Getting used to the Functional Programming way of doing things:
- currying
- destructuring
- pattern matching
- expressive types
-
no loops, rather mapping and folding
-
only mutate indirectly in fold (by returning value)
Getting used to FRP way of doing things:
- most variables are signals
- no direct control flow
- define the graph
- type system + TEA makes things converge
Way to Elm
Conclusion
FRP:
-
can help you contain complexity
-
can give you better debugging tools
-
is already used in production (Elm)
References
That's all folks!
@doppioslash
@doppioslash
See you on twitter :)