20. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
In computing, reactive programming is a programming
paradigm oriented around data flows and the
propagation of change.This means that it should be
possible to express static or dynamic data flows with
ease in the programming languages used, and that the
underlying execution model will automatically
propagate changes through the data flow.
22. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Scalable
ResilientReplication
High-Availability
Elasticity
Non-Blocking
Asynchronous
Message-Passing
Isolation
Containment
Location-Transparency
Loose-Coupling
23. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Reactive Programming =
24. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
bit.ly/1sb5hCu
Reactive is Dead,
long live composing side effects.
25. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
“One thing I’m discovering is
that transforming data is
easier to think about than
maintaining state.”
!
- Dave Thomas
26. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
let y = f(x)
Imperative Functional
x.f()
27. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
mutation
let y = f(x)
Imperative Functional
x.f()
29. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Move Up
Move Down
30. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
private var arrowKeyUp:Bool;
private var arrowKeyDown:Bool;
!
private var platform1:Platform;
private var platform2:Platform;
private var ball:Ball;
31. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
function keyDown(event:KeyboardEvent):Void {
if (currentGameState == Paused &&
event.keyCode == 32) {
setGameState(Playing);
} else if (event.keyCode == 38) {
arrowKeyUp = true;
} else if (event.keyCode == 40) {
arrowKeyDown = true;
}
}
32. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
function keyUp(event:KeyboardEvent):Void {
if (event.keyCode == 38) {
arrowKeyUp = false;
} else if (event.keyCode == 40) {
arrowKeyDown = false;
}
}
33. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
function everyFrame(event:Event):Void {
if(currentGameState == Playing){
if (arrowKeyUp) {
platform1.y -= platformSpeed;
}
if (arrowKeyDown) {
platform1.y += platformSpeed;
}
if (platform1.y < 5) platform1.y = 5;
if (platform1.y > 395) platform1.y = 395;
}
}
34. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
function everyFrame(event:Event):Void {
if(currentGameState == Playing){
if (arrowKeyUp) {
platform1.y -= platformSpeed;
}
if (arrowKeyDown) {
platform1.y += platformSpeed;
}
if (platform1.y < 5) platform1.y = 5;
if (platform1.y > 395) platform1.y = 395;
}
}
35. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
source files
state changes
36. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
source files execution
37. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
source files execution
38. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
mental model
input state new state behaviour
{ x; y } { x; y-speed }
{ x; y } { x; y+speed }
timer { x; y } { x; y } draw platform
… … … …
39. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
transformation
let y = f(x)
Imperative Functional
x.f()
40. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Transformations
simplify problem
decomposition
41. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Move Up
Move Down
42. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Platform = {x:Int, y:Int}
defaultPlatform = {x=5, y=0}
!
delta = Time.fps 20
input = Signal.sampleOn delta Keyboard.arrows
!
cap x = max 5 <| min x 395
!
p1 : Signal Platform
p1 = foldp ({x, y} s -> {s | y <- cap <| s.y + 5*y})
defaultPlatform
input
43. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Platform = {x:Int, y:Int}
defaultPlatform = {x=5, y=0}
!
delta = Time.fps 20
input = Signal.sampleOn delta Keyboard.arrows
!
cap x = max 5 <| min x 395
!
p1 : Signal Platform
p1 = foldp ({x, y} s -> {s | y <- cap <| s.y + 5*y})
defaultPlatform
input
44. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Platform = {x:Int, y:Int}
defaultPlatform = {x=5, y=0}
!
delta = Time.fps 20
input = Signal.sampleOn delta Keyboard.arrows
!
cap x = max 5 <| min x 395
!
p1 : Signal Platform
p1 = foldp ({x, y} s -> {s | y <- cap <| s.y + 5*y})
defaultPlatform
input
45. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
UP
{ x=0, y=1 }
DOWN
{ x=0, y=-1 }
LEFT
{ x=-1, y=0 }
RIGHT
{ x=1, y=0 }
46. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Platform = {x:Int, y:Int}
defaultPlatform = {x=5, y=0}
!
delta = Time.fps 20
input = Signal.sampleOn delta Keyboard.arrows
!
cap x = max 5 <| min x 395
!
p1 : Signal Platform
p1 = foldp ({x, y} s -> {s | y <- cap <| s.y + 5*y})
defaultPlatform
input
47. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Platform = {x:Int, y:Int}
defaultPlatform = {x=5, y=0}
!
delta = Time.fps 20
input = Signal.sampleOn delta Keyboard.arrows
!
cap x = max 5 <| min x 395
!
p1 : Signal Platform
p1 = foldp ({x, y} s -> {s | y <- cap <| s.y + 5*y})
defaultPlatform
input
48. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Platform = {x:Int, y:Int}
defaultPlatform = {x=5, y=0}
!
delta = Time.fps 20
input = Signal.sampleOn delta Keyboard.arrows
!
cap x = max 5 <| min x 395
!
p1 : Signal Platform
p1 = foldp ({x, y} s -> {s | y <- cap <| s.y + 5*y})
defaultPlatform
input
49. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Platform = {x:Int, y:Int}
defaultPlatform = {x=5, y=0}
!
delta = Time.fps 20
input = Signal.sampleOn delta Keyboard.arrows
!
cap x = max 5 <| min x 395
!
p1 : Signal Platform
p1 = foldp ({x, y} s -> {s | y <- cap <| s.y + 5*y})
defaultPlatform
input
50. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Platform = {x:Int, y:Int}
defaultPlatform = {x=5, y=0}
!
delta = Time.fps 20
input = Signal.sampleOn delta Keyboard.arrows
!
cap x = max 5 <| min x 395
!
p1 : Signal Platform
p1 = foldp ({x, y} s -> {s | y <- cap <| s.y + 5*y})
defaultPlatform
input
51. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Rx Dart Elm
Observable Stream Signal
= =
58. BOLOGNA 28 march 2015 LambdaCon
Yan Cui (@theburningmonk)
my adventure with Elm
59. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
http://bit.ly/1wV46XS
60. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Elm Basics
61. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
add x y = x + y
62. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
add : Int -> Int -> Int
add x y = x + y
63. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
calcAngle start end =
let
distH
= end.x - start.x
distV
= end.y - start.y
in atan2 distV distH
64. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
calcAngle start end =
let
distH
= end.x - start.x
distV
= end.y - start.y
in atan2 distV distH
65. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
calcAngle start end =
let
distH
= end.x - start.x
distV
= end.y - start.y
in atan2 distV distH
66. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
multiply x y
= x * y
triple = multiply 3
67. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
multiply x y
= x * y
triple = multiply 3
68. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
f a b c d = …
f :
Int ->
(Int ->
(Int ->
(Int -> Int)))
69. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
double list = List.map (x -> x * 2) list
70. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
double list = List.map ((*) 2) list
71. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
tuple1 = (2,“three”)
tuple2 = (2,“three”, [4, 5])
72. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
tuple4 = (,) 2 “three”
tuple5 = (,,) 2 “three” [4, 5]
73. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
x = { age=42, name=“foo” }
74. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
lightweight, labelled
data structure
75. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
x.age
x.name
-- 42
-- “foo”
76. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
x.age
x.name
-- 42
-- “foo”
.age x
.name x
-- 42
-- “foo”
77. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
-- clone and update
y = { x | name <- "bar" }
78. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Character =
{ age : Int, name : String }
79. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type alias Named a = { a | name : String }
type alias Aged a = { a | age : Int }
80. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
lady : Named ( Aged { } )
lady = { name=“foo”, age=42 }
81. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
getName : Named x -> String
getName { name } = name
82. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
getName : Named x -> String
getName { name } = name
!
getName lady
-- “foo”
83. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type Status = Flying Pos Speed
| Exploding Radius
| Exploded
84. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
aka.
“sums-and-products”
data structures
85. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
type Status = Flying Pos Speed
| Exploding Radius
| Exploded
sums :
choice between variants of a type
86. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
products :
tuple of types
type Status = Flying Pos Speed
| Exploding Radius
| Exploded
87. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y radius =
circle radius
|> filled (rgb 150 170 150)
|> alpha 0.5
|> move (x, y)
88. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y radius =
circle radius
|> filled (rgb 150 170 150)
|> alpha 0.5
|> move (x, y)
filled : Color -> Shape -> Form
89. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y radius =
circle radius
|> filled (rgb 150 170 150)
|> alpha 0.5
|> move (x, y)
90. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y radius =
circle radius
|> filled (rgb 150 170 150)
|> alpha 0.5
|> move (x, y)
91. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
“…a clean design is one that supports
visual thinking so people can meet their
informational needs with a minimum of
conscious effort.”
!
- Daniel Higginbotham
(www.visualmess.com)
93. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y radius =
radius |> circle
|> filled (rgb 150 170 150)
|> alpha 0.5
|> move (x, y)
2.top-to-bottom
1. left-to-right
94. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle : Int -> Int -> Float -> Form
95. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
circle
>> filled (rgb 150 170 150)
>> alpha 0.5
>> move (x, y)
96. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
circle
>> filled (rgb 150 170 150)
>> alpha 0.5
>> move (x, y)
circle : Float -> Shape
97. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Shape)
>> filled (rgb 150 170 150)
>> alpha 0.5
>> move (x, y)
98. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Shape)
>> filled (rgb 150 170 150)
>> alpha 0.5
>> move (x, y)
filled : Color -> Shape -> Form
99. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Shape)
>> filled (rgb 150 170 150)
>> alpha 0.5
>> move (x, y)
Curried!
filled : Color -> Shape -> Form
100. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Shape)
>> filled (rgb 150 170 150)
>> alpha 0.5
>> move (x, y)
Shape -> Form
101. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Shape)
>> (Shape -> Form)
>> alpha 0.5
>> move (x, y)
102. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Shape)
>> (Shape -> Form)
>> alpha 0.5
>> move (x, y)
103. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Shape)
>> (Shape -> Form)
>> alpha 0.5
>> move (x, y)
104. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Shape)
>> (Shape -> Form)
>> alpha 0.5
>> move (x, y)
105. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Form)
>> alpha 0.5
>> move (x, y)
106. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Form)
>> (Form -> Form)
>> move (x, y)
107. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Form)
>> (Form -> Form)
>> move (x, y)
108. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Form)
>> move (x, y)
109. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Form)
>> (Form -> Form)
110. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Form)
>> (Form -> Form)
111. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle x y =
(Float -> Form)
112. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
drawCircle : Int -> Int -> (Float -> Form)
113. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
greet name =
case name of
"Yan"
-> “hi, theburningmonk"
_
-> “hi,“ ++ name
114. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
greet name =
case name of
"Yan"
-> “hi, theburningmonk"
_
-> “hi,“ ++ name
115. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
fizzbuzz n =
if | n % 15 == 0
-> "fizz buzz"
| n % 3
== 0
-> "fizz"
| n % 5
== 0
-> "buzz"
| otherwise
-> show n
116. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Mouse.position
Mouse.clicks
Mouse.isDown
…
117. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Window.dimension
Window.width
Window.height
118. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Time.every
Time.fps
Time.timestamp
Time.delay
…
119. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Mouse.position : Signal (Int, Int)
120. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Mouse.position : Signal (Int, Int)
121. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Mouse.position : Signal (Int, Int)
(10, 23) (3, 16) (8, 10) (12, 5) (18, 3)
122. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Keyboard.lastPressed : Signal Int
123. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Keyboard.lastPressed : Signal Int
H E L L O space
124. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
Keyboard.lastPressed : Signal Int
H E L L O space
72 69 76 76 79 32
125. BOLOGNA 28 march 2015 - Yan Cui @theburningmonk LambdaCon
map : (a -> b) -> Signal a -> Signal b