SlideShare a Scribd company logo
1 of 190
Download to read offline
Yan Cui
!
Talk title: My Adventure with Elm
!
theburningmonk@gmail.com - GameSys - @theburningmonk
ROME 27-28 march 2015
ROME 27-28 march 2015 – Yan Cui @theburningmonk
agenda
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Hi, my name isYan Cui.
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
I’m not an expert on Elm.
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Function Reactive
Programming?
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Value over Time
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Time
Value
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Time
Value
Signal
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Reactive is Dead,	

long live composing side effects.
bit.ly/1sb5hCu
ROME 27-28 march 2015 – Yan Cui @theburningmonk
“One thing I’m discovering is
that transforming data is
easier to think about than
maintaining state.”	

!
	

 	

 - Dave Thomas
ROME 27-28 march 2015 – Yan Cui @theburningmonk
let y = f(x)
Imperative Functional
x.f()
ROME 27-28 march 2015 – Yan Cui @theburningmonk
mutation
let y = f(x)
Imperative Functional
x.f()
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Move Up
Move Down
ROME 27-28 march 2015 – Yan Cui @theburningmonk
private var arrowKeyUp:Bool;	

private var arrowKeyDown:Bool;	

!
private var platform1:Platform;	

private var platform2:Platform;	

private var ball:Ball;
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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;
	

 }	

}
ROME 27-28 march 2015 – Yan Cui @theburningmonk
function keyUp(event:KeyboardEvent):Void {	

	

 if (event.keyCode == 38) {	

arrowKeyUp = false;
	

 } else if (event.keyCode == 40) {	

arrowKeyDown = false;
	

 }	

}
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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;	

	

 }	

}
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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;
	

 }	

}
ROME 27-28 march 2015 – Yan Cui @theburningmonk
source files
state changes
ROME 27-28 march 2015 – Yan Cui @theburningmonk
source files execution
ROME 27-28 march 2015 – Yan Cui @theburningmonk
source files execution
ROME 27-28 march 2015 – Yan Cui @theburningmonk
mental model
input state new state behaviour
{ x; y } { x; y-speed }
{ x; y } { x; y+speed }
timer { x; y } { x; y } draw platform
… … … …
ROME 27-28 march 2015 – Yan Cui @theburningmonk
transformation
let y = f(x)
Imperative Functional
x.f()
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Transformations
simplify problem
decomposition
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Move Up
Move Down
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
UP	

 	

 	

 { x=0, y=1 }	

DOWN	

	

 { x=0, y=-1 }	

LEFT	

	

 	

 { x=-1, y=0 }	

RIGHT	

 	

 { x=1, y=0 }
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Rx Dart Elm
Observable Stream Signal
= =
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Idea See in Action
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Yan Cui
!
Talk title: My Adventure with Elm
!
theburningmonk@gmail.com - GameSys - @theburningmonk
ROME 27-28 march 2015
ROME 27-28 march 2015 – Yan Cui @theburningmonk
http://bit.ly/1wV46XS
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Elm Basics
ROME 27-28 march 2015 – Yan Cui @theburningmonk
add x y = x + y
ROME 27-28 march 2015 – Yan Cui @theburningmonk
add : Int -> Int -> Int
add x y = x + y
ROME 27-28 march 2015 – Yan Cui @theburningmonk
calcAngle start end =	

	

 let	

distH	

 = end.x - start.x	

	

	

 distV 	

= end.y - start.y	

	

 in atan2 distV distH
ROME 27-28 march 2015 – Yan Cui @theburningmonk
calcAngle start end =	

	

 let	

distH	

 = end.x - start.x	

	

	

 distV 	

= end.y - start.y	

	

 in atan2 distV distH
ROME 27-28 march 2015 – Yan Cui @theburningmonk
calcAngle start end =	

	

 let	

distH	

 = end.x - start.x	

	

	

 distV 	

= end.y - start.y	

	

 in atan2 distV distH
ROME 27-28 march 2015 – Yan Cui @theburningmonk
multiply x y	

= x * y	

triple = multiply 3
ROME 27-28 march 2015 – Yan Cui @theburningmonk
multiply x y	

= x * y	

triple = multiply 3
ROME 27-28 march 2015 – Yan Cui @theburningmonk
f a b c d = …	

f :	

 Int -> 	

	

 	

 	

 (Int -> 	

	

 	

 	

 	

 (Int -> 	

	

 	

 	

 	

 	

 (Int -> Int)))
ROME 27-28 march 2015 – Yan Cui @theburningmonk
double list = List.map (x -> x * 2) list
ROME 27-28 march 2015 – Yan Cui @theburningmonk
double list = List.map ((*) 2) list
ROME 27-28 march 2015 – Yan Cui @theburningmonk
tuple1 = (2,“three”)	

tuple2 = (2,“three”, [4, 5])
ROME 27-28 march 2015 – Yan Cui @theburningmonk
tuple4 = (,) 2 “three”	

tuple5 = (,,) 2 “three” [4, 5]
ROME 27-28 march 2015 – Yan Cui @theburningmonk
x = { age=42, name=“foo” }
ROME 27-28 march 2015 – Yan Cui @theburningmonk
lightweight, labelled
data structure
ROME 27-28 march 2015 – Yan Cui @theburningmonk
x.age	

x.name
-- 42	

-- “foo”
ROME 27-28 march 2015 – Yan Cui @theburningmonk
x.age	

x.name
-- 42	

-- “foo”
.age x	

.name x
-- 42	

-- “foo”
ROME 27-28 march 2015 – Yan Cui @theburningmonk
-- clone and update	

y = { x | name <- "bar" }
ROME 27-28 march 2015 – Yan Cui @theburningmonk
type alias Character = 	

{ age : Int, name : String }
ROME 27-28 march 2015 – Yan Cui @theburningmonk
type alias Named a = { a | name : String }	

type alias Aged a = { a | age : Int }
ROME 27-28 march 2015 – Yan Cui @theburningmonk
lady : Named ( Aged { } )	

lady = { name=“foo”, age=42 }
ROME 27-28 march 2015 – Yan Cui @theburningmonk
getName : Named x -> String	

getName { name } = name
ROME 27-28 march 2015 – Yan Cui @theburningmonk
getName : Named x -> String	

getName { name } = name	

!
getName lady	

	

 -- “foo”
ROME 27-28 march 2015 – Yan Cui @theburningmonk
type Status = Flying Pos Speed	

	

 	

 	

 	

 	

 	

 	

 | Exploding Radius	

	

 	

 	

 	

 	

 	

 	

 | Exploded
ROME 27-28 march 2015 – Yan Cui @theburningmonk
aka.	

“sums-and-products”	

data structures
ROME 27-28 march 2015 – Yan Cui @theburningmonk
type Status = Flying Pos Speed	

	

 	

 	

 	

 	

 	

 | Exploding Radius	

	

 	

 	

 	

 	

 	

 | Exploded
sums : 	

choice between variants of a type
ROME 27-28 march 2015 – Yan Cui @theburningmonk
products : 	

tuple of types
type Status = Flying Pos Speed	

	

 	

 	

 	

 	

 	

 | Exploding Radius	

	

 	

 	

 	

 	

 	

 | Exploded
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y radius =	

	

 circle radius	

	

|> filled (rgb 150 170 150)	

	

 |> alpha 0.5	

	

 |> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y radius =	

	

 circle radius	

	

|> filled (rgb 150 170 150)	

	

 |> alpha 0.5	

	

 |> move (x, y)	

filled : Color -> Shape -> Form
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y radius =	

	

 circle radius	

	

|> filled (rgb 150 170 150)	

	

 |> alpha 0.5	

	

 |> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y radius =	

	

 circle radius	

	

|> filled (rgb 150 170 150)	

	

 |> alpha 0.5	

	

 |> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
“…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)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
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
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle : Int -> Int -> Float -> Form
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 circle 	

	

>> filled (rgb 150 170 150)	

	

>> alpha 0.5	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 circle 	

	

>> filled (rgb 150 170 150)	

	

>> alpha 0.5	

	

>> move (x, y)
circle : Float -> Shape
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Shape) 	

	

>> filled (rgb 150 170 150)	

	

>> alpha 0.5	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Shape) 	

	

>> filled (rgb 150 170 150)	

	

>> alpha 0.5	

	

>> move (x, y)
filled : Color -> Shape -> Form
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Shape) 	

	

>> filled (rgb 150 170 150)	

	

>> alpha 0.5	

	

>> move (x, y)
Curried!
filled : Color -> Shape -> Form
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Shape) 	

	

>> filled (rgb 150 170 150)	

	

>> alpha 0.5	

	

>> move (x, y)
Shape -> Form
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Shape) 	

	

>> (Shape -> Form)	

	

>> alpha 0.5	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Shape) 	

	

>> (Shape -> Form) 	

	

>> alpha 0.5	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Shape) 	

	

>> (Shape -> Form) 	

	

>> alpha 0.5	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Shape) 	

	

>> (Shape -> Form) 	

	

>> alpha 0.5	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Form)	

	

>> alpha 0.5	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Form)	

	

>> (Form -> Form)	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Form)	

	

>> (Form -> Form)	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Form)	

	

>> move (x, y)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Form)	

	

>> (Form -> Form)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Form)	

	

>> (Form -> Form)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle x y =	

	

 (Float -> Form)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
drawCircle : Int -> Int -> (Float -> Form)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
greet name =	

case name of 	

"Yan" 	

-> “hi, theburningmonk"	

_ 	

	

 -> “hi,“ ++ name
ROME 27-28 march 2015 – Yan Cui @theburningmonk
greet name =	

case name of 	

"Yan" 	

-> “hi, theburningmonk"	

_ 	

	

 -> “hi,“ ++ name
ROME 27-28 march 2015 – Yan Cui @theburningmonk
fizzbuzz n =	

if | n % 15 == 0	

-> "fizz buzz"	

| n % 3 	

== 0	

-> "fizz"	

| n % 5 	

== 0	

-> "buzz"	

| otherwise 	

-> show n
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Mouse.position	

Mouse.clicks	

Mouse.isDown	

…
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Window.dimension	

Window.width	

Window.height
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Time.every	

Time.fps	

Time.timestamp	

Time.delay	

…
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Mouse.position : Signal (Int, Int)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Mouse.position : Signal (Int, Int)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Mouse.position : Signal (Int, Int)
(10, 23) (3, 16) (8, 10) (12, 5) (18, 3)
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Keyboard.lastPressed : Signal Int
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Keyboard.lastPressed : Signal Int
H E L L O space
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Keyboard.lastPressed : Signal Int
H E L L O space
72 69 76 76 79 32
ROME 27-28 march 2015 – Yan Cui @theburningmonk
map : (a -> b) -> Signal a -> Signal b
ROME 27-28 march 2015 – Yan Cui @theburningmonk
<~
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Signal of num of pixels in window
ROME 27-28 march 2015 – Yan Cui @theburningmonk
((w, h) -> w*h) <~ Window.dimensions
ROME 27-28 march 2015 – Yan Cui @theburningmonk
((w, h) -> w*h) <~ Window.dimensions
Signal (Int, Int)(Int, Int) -> Int
ROME 27-28 march 2015 – Yan Cui @theburningmonk
((w, h) -> w*h) <~ Window.dimensions
Signal (Int, Int)(Int, Int) -> Int
Signal Int
ROME 27-28 march 2015 – Yan Cui @theburningmonk
(10, 10) (15, 10) (18, 12)
100 150 216
((w, h) -> w*h) <~ Window.dimensions
ROME 27-28 march 2015 – Yan Cui @theburningmonk
map2 : (a -> b -> c) 	

	

 	

 	

 	

 -> Signal a 	

	

 	

 	

 	

 -> Signal b 	

	

 	

 	

 	

 -> Signal c
ROME 27-28 march 2015 – Yan Cui @theburningmonk
~
ROME 27-28 march 2015 – Yan Cui @theburningmonk
(,) <~ Window.width ~ Window.height
Signal Int
a -> b -> (a, b)
Signal Int
ROME 27-28 march 2015 – Yan Cui @theburningmonk
(,) <~ Window.width ~ Window.height
Signal Int
Int -> Int -> (Int, Int)
Signal Int
ROME 27-28 march 2015 – Yan Cui @theburningmonk
map3 : (a -> b -> c -> d) 	

	

 	

 	

 	

 -> Signal a 	

	

 	

 	

 	

 -> Signal b 	

	

 	

 	

 	

 -> Signal c	

	

 	

 	

 	

 -> Signal d
ROME 27-28 march 2015 – Yan Cui @theburningmonk
(,,) <~ signalA ~ signalB ~ signalC
ROME 27-28 march 2015 – Yan Cui @theburningmonk
map4 : …	

map5 : …	

map6 : …	

map7 : …	

map8 : …
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp : (a -> b -> b) 	

	

 	

 	

 	

 -> b 	

	

 	

 	

 	

 -> Signal a 	

	

 	

 	

 	

 -> Signal b
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp : (a -> b -> b) 	

	

 	

 	

 	

 -> b
	

 	

 	

 	

 -> Signal a 	

	

 	

 	

 	

 -> Signal b
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp : (a -> b -> b) 	

	

 	

 	

 	

 -> b
	

 	

 	

 	

 -> Signal a 	

	

 	

 	

 	

 -> Signal b
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp : (a -> b -> b) 	

	

 	

 	

 -> b 	

	

 	

 	

 	

 -> Signal a 	

	

 	

 	

 	

 -> Signal b
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp : (a -> b -> b) 	

	

 	

 	

 	

 -> b 	

	

 	

 	

 	

 -> Signal a 	

	

 	

 	

 	

 -> Signal b
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp : (a -> b -> b) 	

	

 	

 	

 	

 -> b 	

	

 	

 	

 	

 -> Signal a 	

	

 	

 	

 	

 -> Signal b
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp (_ n -> n + 1) 0 Mouse.clicks
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp (_ n -> n + 1) 0 Mouse.clicks
ROME 27-28 march 2015 – Yan Cui @theburningmonk
foldp (_ n -> n + 1) 0 Mouse.clicks
ROME 27-28 march 2015 – Yan Cui @theburningmonk
1 3 42 5
foldp (_ n -> n + 1) 0 Mouse.clicks
ROME 27-28 march 2015 – Yan Cui @theburningmonk
UP	

	

 	

 	

 { x=0, y=1 }	

DOWN	

 { x=0, y=-1 }	

LEFT	

	

 	

 { x=-1, y=0 }	

RIGHT	

	

 { x=1, y=0 }
ROME 27-28 march 2015 – Yan Cui @theburningmonk
merge	

 : Signal a -> Signal a -> Signal a	

mergeMany : List (Signal a) -> Signal a	

…
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Js Interop,
WebGL
HTML layout,
dependency management,
etc.
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
8 segments
ROME 27-28 march 2015 – Yan Cui @theburningmonk
direction
ROME 27-28 march 2015 – Yan Cui @theburningmonk
change
change
no changenot allowed
direction
ROME 27-28 march 2015 – Yan Cui @theburningmonk
direction
ROME 27-28 march 2015 – Yan Cui @theburningmonk
direction
ROME 27-28 march 2015 – Yan Cui @theburningmonk
direction
ROME 27-28 march 2015 – Yan Cui @theburningmonk
direction
ROME 27-28 march 2015 – Yan Cui @theburningmonk
direction
cherry
ROME 27-28 march 2015 – Yan Cui @theburningmonk
direction
YUMYUMYUM!
ROME 27-28 march 2015 – Yan Cui @theburningmonk
direction
+1 segment
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Demo
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
github.com/theburningmonk/elm-snake
github.com/theburningmonk/elm-missile-
command
Missile Command
Snake
ROME 27-28 march 2015 – Yan Cui @theburningmonk
elm-lang.org/try
debug.elm-lang.org/try
ROME 27-28 march 2015 – Yan Cui @theburningmonk
the
 not
 so
 great
 things
ROME 27-28 march 2015 – Yan Cui @theburningmonk
Type error between lines 63 and 85:	

case gameState of	

NotStarted - if | userInput == Space -	

Started (defaultSnake,Nothing)	

| True - gameState	

Started ({segments,direction},cherry) - let arrow = case userInput	

of	

Arrow arrow - arrow	

_ - {x = 0, y = 0}	

newDirection = getNewDirection	

arrow direction	

newHead = getNewSegment	

(List.head segments) newDirection	

newTail = List.take	

((List.length segments) - 1)	

segments	

(w,h) = windowDims	

isGameOver = (List.any	

(t - t == newHead)	

newTail) ||	

(((fst newHead) 	

((toFloat w) / 2)) ||	

(((snd newHead) 	

((toFloat h) / 2)) ||	

(((fst newHead) 	

((toFloat (-w)) / 2)) ||	

((snd newHead) 	

((toFloat (-h)) / 2)))))	

in if | isGameOver - NotStarted	

| True -	

Started	

({segments = newHead :: newTail,	

direction = newDirection},	

cherry)	

!
Expected Type: {}	

Actual Type: Snake.Input
cryptic error
messages
ROME 27-28 march 2015 – Yan Cui @theburningmonk
breaking changes
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk
ROME 27-28 march 2015 – Yan Cui @theburningmonk

More Related Content

More from Codemotion

More from Codemotion (20)

Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...
 
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019
 
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019
 
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019
 

Recently uploaded

Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 

Recently uploaded (20)

Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 

My adventure with Elm - Yan Cui - Codemotion Roma 2015

  • 1. Yan Cui ! Talk title: My Adventure with Elm ! theburningmonk@gmail.com - GameSys - @theburningmonk ROME 27-28 march 2015
  • 2. ROME 27-28 march 2015 – Yan Cui @theburningmonk agenda
  • 3. ROME 27-28 march 2015 – Yan Cui @theburningmonk Hi, my name isYan Cui.
  • 4. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 5. ROME 27-28 march 2015 – Yan Cui @theburningmonk I’m not an expert on Elm.
  • 6. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 7. ROME 27-28 march 2015 – Yan Cui @theburningmonk Function Reactive Programming?
  • 8. ROME 27-28 march 2015 – Yan Cui @theburningmonk Value over Time
  • 9. ROME 27-28 march 2015 – Yan Cui @theburningmonk Time Value
  • 10. ROME 27-28 march 2015 – Yan Cui @theburningmonk Time Value Signal
  • 11. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 12. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 13. ROME 27-28 march 2015 – Yan Cui @theburningmonk Reactive is Dead, long live composing side effects. bit.ly/1sb5hCu
  • 14. ROME 27-28 march 2015 – Yan Cui @theburningmonk “One thing I’m discovering is that transforming data is easier to think about than maintaining state.” ! - Dave Thomas
  • 15. ROME 27-28 march 2015 – Yan Cui @theburningmonk let y = f(x) Imperative Functional x.f()
  • 16. ROME 27-28 march 2015 – Yan Cui @theburningmonk mutation let y = f(x) Imperative Functional x.f()
  • 17. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 18. ROME 27-28 march 2015 – Yan Cui @theburningmonk Move Up Move Down
  • 19. ROME 27-28 march 2015 – Yan Cui @theburningmonk private var arrowKeyUp:Bool; private var arrowKeyDown:Bool; ! private var platform1:Platform; private var platform2:Platform; private var ball:Ball;
  • 20. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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; } }
  • 21. ROME 27-28 march 2015 – Yan Cui @theburningmonk function keyUp(event:KeyboardEvent):Void { if (event.keyCode == 38) { arrowKeyUp = false; } else if (event.keyCode == 40) { arrowKeyDown = false; } }
  • 22. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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; } }
  • 23. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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; } }
  • 24. ROME 27-28 march 2015 – Yan Cui @theburningmonk source files state changes
  • 25. ROME 27-28 march 2015 – Yan Cui @theburningmonk source files execution
  • 26. ROME 27-28 march 2015 – Yan Cui @theburningmonk source files execution
  • 27. ROME 27-28 march 2015 – Yan Cui @theburningmonk mental model input state new state behaviour { x; y } { x; y-speed } { x; y } { x; y+speed } timer { x; y } { x; y } draw platform … … … …
  • 28. ROME 27-28 march 2015 – Yan Cui @theburningmonk transformation let y = f(x) Imperative Functional x.f()
  • 29. ROME 27-28 march 2015 – Yan Cui @theburningmonk Transformations simplify problem decomposition
  • 30. ROME 27-28 march 2015 – Yan Cui @theburningmonk Move Up Move Down
  • 31. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 32. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 33. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 34. ROME 27-28 march 2015 – Yan Cui @theburningmonk UP { x=0, y=1 } DOWN { x=0, y=-1 } LEFT { x=-1, y=0 } RIGHT { x=1, y=0 }
  • 35. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 36. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 37. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 38. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 39. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 40. ROME 27-28 march 2015 – Yan Cui @theburningmonk Rx Dart Elm Observable Stream Signal = =
  • 41. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 42. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 43. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 44. ROME 27-28 march 2015 – Yan Cui @theburningmonk Idea See in Action
  • 45. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 46. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 47. Yan Cui ! Talk title: My Adventure with Elm ! theburningmonk@gmail.com - GameSys - @theburningmonk ROME 27-28 march 2015
  • 48. ROME 27-28 march 2015 – Yan Cui @theburningmonk http://bit.ly/1wV46XS
  • 49. ROME 27-28 march 2015 – Yan Cui @theburningmonk Elm Basics
  • 50. ROME 27-28 march 2015 – Yan Cui @theburningmonk add x y = x + y
  • 51. ROME 27-28 march 2015 – Yan Cui @theburningmonk add : Int -> Int -> Int add x y = x + y
  • 52. ROME 27-28 march 2015 – Yan Cui @theburningmonk calcAngle start end = let distH = end.x - start.x distV = end.y - start.y in atan2 distV distH
  • 53. ROME 27-28 march 2015 – Yan Cui @theburningmonk calcAngle start end = let distH = end.x - start.x distV = end.y - start.y in atan2 distV distH
  • 54. ROME 27-28 march 2015 – Yan Cui @theburningmonk calcAngle start end = let distH = end.x - start.x distV = end.y - start.y in atan2 distV distH
  • 55. ROME 27-28 march 2015 – Yan Cui @theburningmonk multiply x y = x * y triple = multiply 3
  • 56. ROME 27-28 march 2015 – Yan Cui @theburningmonk multiply x y = x * y triple = multiply 3
  • 57. ROME 27-28 march 2015 – Yan Cui @theburningmonk f a b c d = … f : Int -> (Int -> (Int -> (Int -> Int)))
  • 58. ROME 27-28 march 2015 – Yan Cui @theburningmonk double list = List.map (x -> x * 2) list
  • 59. ROME 27-28 march 2015 – Yan Cui @theburningmonk double list = List.map ((*) 2) list
  • 60. ROME 27-28 march 2015 – Yan Cui @theburningmonk tuple1 = (2,“three”) tuple2 = (2,“three”, [4, 5])
  • 61. ROME 27-28 march 2015 – Yan Cui @theburningmonk tuple4 = (,) 2 “three” tuple5 = (,,) 2 “three” [4, 5]
  • 62. ROME 27-28 march 2015 – Yan Cui @theburningmonk x = { age=42, name=“foo” }
  • 63. ROME 27-28 march 2015 – Yan Cui @theburningmonk lightweight, labelled data structure
  • 64. ROME 27-28 march 2015 – Yan Cui @theburningmonk x.age x.name -- 42 -- “foo”
  • 65. ROME 27-28 march 2015 – Yan Cui @theburningmonk x.age x.name -- 42 -- “foo” .age x .name x -- 42 -- “foo”
  • 66. ROME 27-28 march 2015 – Yan Cui @theburningmonk -- clone and update y = { x | name <- "bar" }
  • 67. ROME 27-28 march 2015 – Yan Cui @theburningmonk type alias Character = { age : Int, name : String }
  • 68. ROME 27-28 march 2015 – Yan Cui @theburningmonk type alias Named a = { a | name : String } type alias Aged a = { a | age : Int }
  • 69. ROME 27-28 march 2015 – Yan Cui @theburningmonk lady : Named ( Aged { } ) lady = { name=“foo”, age=42 }
  • 70. ROME 27-28 march 2015 – Yan Cui @theburningmonk getName : Named x -> String getName { name } = name
  • 71. ROME 27-28 march 2015 – Yan Cui @theburningmonk getName : Named x -> String getName { name } = name ! getName lady -- “foo”
  • 72. ROME 27-28 march 2015 – Yan Cui @theburningmonk type Status = Flying Pos Speed | Exploding Radius | Exploded
  • 73. ROME 27-28 march 2015 – Yan Cui @theburningmonk aka. “sums-and-products” data structures
  • 74. ROME 27-28 march 2015 – Yan Cui @theburningmonk type Status = Flying Pos Speed | Exploding Radius | Exploded sums : choice between variants of a type
  • 75. ROME 27-28 march 2015 – Yan Cui @theburningmonk products : tuple of types type Status = Flying Pos Speed | Exploding Radius | Exploded
  • 76. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)
  • 77. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y) filled : Color -> Shape -> Form
  • 78. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)
  • 79. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)
  • 80. ROME 27-28 march 2015 – Yan Cui @theburningmonk “…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)
  • 81. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 82. ROME 27-28 march 2015 – Yan Cui @theburningmonk 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
  • 83. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle : Int -> Int -> Float -> Form
  • 84. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = circle >> filled (rgb 150 170 150) >> alpha 0.5 >> move (x, y)
  • 85. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = circle >> filled (rgb 150 170 150) >> alpha 0.5 >> move (x, y) circle : Float -> Shape
  • 86. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Shape) >> filled (rgb 150 170 150) >> alpha 0.5 >> move (x, y)
  • 87. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Shape) >> filled (rgb 150 170 150) >> alpha 0.5 >> move (x, y) filled : Color -> Shape -> Form
  • 88. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Shape) >> filled (rgb 150 170 150) >> alpha 0.5 >> move (x, y) Curried! filled : Color -> Shape -> Form
  • 89. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Shape) >> filled (rgb 150 170 150) >> alpha 0.5 >> move (x, y) Shape -> Form
  • 90. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Shape) >> (Shape -> Form) >> alpha 0.5 >> move (x, y)
  • 91. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Shape) >> (Shape -> Form) >> alpha 0.5 >> move (x, y)
  • 92. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Shape) >> (Shape -> Form) >> alpha 0.5 >> move (x, y)
  • 93. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Shape) >> (Shape -> Form) >> alpha 0.5 >> move (x, y)
  • 94. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Form) >> alpha 0.5 >> move (x, y)
  • 95. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Form) >> (Form -> Form) >> move (x, y)
  • 96. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Form) >> (Form -> Form) >> move (x, y)
  • 97. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Form) >> move (x, y)
  • 98. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Form) >> (Form -> Form)
  • 99. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Form) >> (Form -> Form)
  • 100. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle x y = (Float -> Form)
  • 101. ROME 27-28 march 2015 – Yan Cui @theburningmonk drawCircle : Int -> Int -> (Float -> Form)
  • 102. ROME 27-28 march 2015 – Yan Cui @theburningmonk greet name = case name of "Yan" -> “hi, theburningmonk" _ -> “hi,“ ++ name
  • 103. ROME 27-28 march 2015 – Yan Cui @theburningmonk greet name = case name of "Yan" -> “hi, theburningmonk" _ -> “hi,“ ++ name
  • 104. ROME 27-28 march 2015 – Yan Cui @theburningmonk fizzbuzz n = if | n % 15 == 0 -> "fizz buzz" | n % 3 == 0 -> "fizz" | n % 5 == 0 -> "buzz" | otherwise -> show n
  • 105. ROME 27-28 march 2015 – Yan Cui @theburningmonk Mouse.position Mouse.clicks Mouse.isDown …
  • 106. ROME 27-28 march 2015 – Yan Cui @theburningmonk Window.dimension Window.width Window.height
  • 107. ROME 27-28 march 2015 – Yan Cui @theburningmonk Time.every Time.fps Time.timestamp Time.delay …
  • 108. ROME 27-28 march 2015 – Yan Cui @theburningmonk Mouse.position : Signal (Int, Int)
  • 109. ROME 27-28 march 2015 – Yan Cui @theburningmonk Mouse.position : Signal (Int, Int)
  • 110. ROME 27-28 march 2015 – Yan Cui @theburningmonk Mouse.position : Signal (Int, Int) (10, 23) (3, 16) (8, 10) (12, 5) (18, 3)
  • 111. ROME 27-28 march 2015 – Yan Cui @theburningmonk Keyboard.lastPressed : Signal Int
  • 112. ROME 27-28 march 2015 – Yan Cui @theburningmonk Keyboard.lastPressed : Signal Int H E L L O space
  • 113. ROME 27-28 march 2015 – Yan Cui @theburningmonk Keyboard.lastPressed : Signal Int H E L L O space 72 69 76 76 79 32
  • 114. ROME 27-28 march 2015 – Yan Cui @theburningmonk map : (a -> b) -> Signal a -> Signal b
  • 115. ROME 27-28 march 2015 – Yan Cui @theburningmonk <~
  • 116. ROME 27-28 march 2015 – Yan Cui @theburningmonk Signal of num of pixels in window
  • 117. ROME 27-28 march 2015 – Yan Cui @theburningmonk ((w, h) -> w*h) <~ Window.dimensions
  • 118. ROME 27-28 march 2015 – Yan Cui @theburningmonk ((w, h) -> w*h) <~ Window.dimensions Signal (Int, Int)(Int, Int) -> Int
  • 119. ROME 27-28 march 2015 – Yan Cui @theburningmonk ((w, h) -> w*h) <~ Window.dimensions Signal (Int, Int)(Int, Int) -> Int Signal Int
  • 120. ROME 27-28 march 2015 – Yan Cui @theburningmonk (10, 10) (15, 10) (18, 12) 100 150 216 ((w, h) -> w*h) <~ Window.dimensions
  • 121. ROME 27-28 march 2015 – Yan Cui @theburningmonk map2 : (a -> b -> c) -> Signal a -> Signal b -> Signal c
  • 122. ROME 27-28 march 2015 – Yan Cui @theburningmonk ~
  • 123. ROME 27-28 march 2015 – Yan Cui @theburningmonk (,) <~ Window.width ~ Window.height Signal Int a -> b -> (a, b) Signal Int
  • 124. ROME 27-28 march 2015 – Yan Cui @theburningmonk (,) <~ Window.width ~ Window.height Signal Int Int -> Int -> (Int, Int) Signal Int
  • 125. ROME 27-28 march 2015 – Yan Cui @theburningmonk map3 : (a -> b -> c -> d) -> Signal a -> Signal b -> Signal c -> Signal d
  • 126. ROME 27-28 march 2015 – Yan Cui @theburningmonk (,,) <~ signalA ~ signalB ~ signalC
  • 127. ROME 27-28 march 2015 – Yan Cui @theburningmonk map4 : … map5 : … map6 : … map7 : … map8 : …
  • 128. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp : (a -> b -> b) -> b -> Signal a -> Signal b
  • 129. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp : (a -> b -> b) -> b -> Signal a -> Signal b
  • 130. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp : (a -> b -> b) -> b -> Signal a -> Signal b
  • 131. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp : (a -> b -> b) -> b -> Signal a -> Signal b
  • 132. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp : (a -> b -> b) -> b -> Signal a -> Signal b
  • 133. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp : (a -> b -> b) -> b -> Signal a -> Signal b
  • 134. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp (_ n -> n + 1) 0 Mouse.clicks
  • 135. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp (_ n -> n + 1) 0 Mouse.clicks
  • 136. ROME 27-28 march 2015 – Yan Cui @theburningmonk foldp (_ n -> n + 1) 0 Mouse.clicks
  • 137. ROME 27-28 march 2015 – Yan Cui @theburningmonk 1 3 42 5 foldp (_ n -> n + 1) 0 Mouse.clicks
  • 138. ROME 27-28 march 2015 – Yan Cui @theburningmonk UP { x=0, y=1 } DOWN { x=0, y=-1 } LEFT { x=-1, y=0 } RIGHT { x=1, y=0 }
  • 139. ROME 27-28 march 2015 – Yan Cui @theburningmonk merge : Signal a -> Signal a -> Signal a mergeMany : List (Signal a) -> Signal a …
  • 140. ROME 27-28 march 2015 – Yan Cui @theburningmonk Js Interop, WebGL HTML layout, dependency management, etc.
  • 141. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 142. ROME 27-28 march 2015 – Yan Cui @theburningmonk 8 segments
  • 143. ROME 27-28 march 2015 – Yan Cui @theburningmonk direction
  • 144. ROME 27-28 march 2015 – Yan Cui @theburningmonk change change no changenot allowed direction
  • 145. ROME 27-28 march 2015 – Yan Cui @theburningmonk direction
  • 146. ROME 27-28 march 2015 – Yan Cui @theburningmonk direction
  • 147. ROME 27-28 march 2015 – Yan Cui @theburningmonk direction
  • 148. ROME 27-28 march 2015 – Yan Cui @theburningmonk direction
  • 149. ROME 27-28 march 2015 – Yan Cui @theburningmonk direction cherry
  • 150. ROME 27-28 march 2015 – Yan Cui @theburningmonk direction YUMYUMYUM!
  • 151. ROME 27-28 march 2015 – Yan Cui @theburningmonk direction +1 segment
  • 152. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 153. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 154. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 155. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 156. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 157. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 158. ROME 27-28 march 2015 – Yan Cui @theburningmonk Demo
  • 159. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 160. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 161. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 162. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 163. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 164. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 165. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 166. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 167. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 168. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 169. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 170. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 171. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 172. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 173. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 174. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 175. ROME 27-28 march 2015 – Yan Cui @theburningmonk github.com/theburningmonk/elm-snake github.com/theburningmonk/elm-missile- command Missile Command Snake
  • 176. ROME 27-28 march 2015 – Yan Cui @theburningmonk elm-lang.org/try debug.elm-lang.org/try
  • 177. ROME 27-28 march 2015 – Yan Cui @theburningmonk the
  • 178.  not
  • 179.  so
  • 182. ROME 27-28 march 2015 – Yan Cui @theburningmonk Type error between lines 63 and 85: case gameState of NotStarted - if | userInput == Space - Started (defaultSnake,Nothing) | True - gameState Started ({segments,direction},cherry) - let arrow = case userInput of Arrow arrow - arrow _ - {x = 0, y = 0} newDirection = getNewDirection arrow direction newHead = getNewSegment (List.head segments) newDirection newTail = List.take ((List.length segments) - 1) segments (w,h) = windowDims isGameOver = (List.any (t - t == newHead) newTail) || (((fst newHead) ((toFloat w) / 2)) || (((snd newHead) ((toFloat h) / 2)) || (((fst newHead) ((toFloat (-w)) / 2)) || ((snd newHead) ((toFloat (-h)) / 2))))) in if | isGameOver - NotStarted | True - Started ({segments = newHead :: newTail, direction = newDirection}, cherry) ! Expected Type: {} Actual Type: Snake.Input cryptic error messages
  • 183. ROME 27-28 march 2015 – Yan Cui @theburningmonk breaking changes
  • 184. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 185. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 186. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 187. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 188. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 189. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 190. ROME 27-28 march 2015 – Yan Cui @theburningmonk
  • 191. ROME 27-28 march 2015 – Yan Cui @theburningmonk @theburningmonk github.com/theburningmonk theburningmonk.com
  • 192.
  • 194. ROME 27-28 march 2015 – Yan Cui @theburningmonk Leave your feedback on Joind.in! https://joind.in/14145 ! !