my adventure with elm - yan cui - codemotion roma 2015

Post on 15-Jul-2015

153 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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 is Yan 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

ValueSignal

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 ElmObservable 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 -> Intadd 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

YUM YUM YUM!

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

ROME 27-28 march 2015 – Yan Cui @theburningmonk

@theburningmonk

github.com/theburningmonk

theburningmonk.com

http://hire.jobvite.com/m?3OHq4hwL

F#

C#

AWSErlang

Docker

micro-services

elasticsearch

redisGoogle

AppEngine

Google BigQuery

PostSharpNeo4j

Python DevOps

PagerDuty

NewRelic

ROME 27-28 march 2015 – Yan Cui @theburningmonk

Leave your feedback on Joind.in! https://joind.in/14145 !!

top related