SlideShare a Scribd company logo
1 of 180
Download to read offline
F# in Social GamingF# in Social Gaming
Yan Cui (@theburningmonk)
agenda
Hi, my name is Yan Cui.
1MILLION USERS
ACTIVE
DAILY
250MILLION DAY
PER
REQUEST
why F#?
time to market
correctness
efficient
tame complexity
Implementing
a slots
engine
Collectables
Wager Size
Special Symbol
Avg Wager Size
Web Server call
• Line Win!
– X number of matching symbols on adjacent columns!
– Positions have to be a ‘line’!
– Wild symbols substitute for other symbols!
!
• Scatter Win!
– X number of matching symbols anywhere!
– Triggers bonus game
What symbols should land?!
Any special symbol wins?!
Did the player win anything?
What the player’s new
average wager?
Should the player receive
collectables?
type Symbol = Standard! of string!
! ! ! | Wild
type Symbol = Standard! of string!
! ! ! | Wild
e.g.! Standard “hat”!
! Standard “shoe”!
! Standard “bonus”!
! …
type Symbol = Standard! of string!
! ! ! | Wild
i.e.! Wild
!
!
!
type Win = LineWin of int * Symbol * int!
! | ScatterWin of Symbol * int
!
!
!
type Win = LineWin of int * Symbol * int!
! | ScatterWin of Symbol * int
e.g.! LineWin (5, Standard “shoe”, 4)
!
!
!
type Win = LineWin of int * Symbol * int!
! | ScatterWin of Symbol * int
e.g.! ScatterWin (Standard “bonus”, 3)
type LineNum = int!
type Count! = int!
!
type Win = LineWin of LineNum * Symbol * Count!
! | ScatterWin of Symbol * Count
type LineNum = int!
type Count! = int!
!
type Win = LineWin of LineNum * Symbol * Count!
! | ScatterWin of Symbol * Count
e.g.! LineWin (5, Standard “shoe”, 4)
type LineNum = int!
type Count! = int!
!
type Win = LineWin of LineNum * Symbol * Count!
! | ScatterWin of Symbol * Count
e.g.! ScatterWin (Standard “bonus”, 3)
make invalid states
unrepresentable
NASA orbiter crashed
because one engineer
accidentally used miles
instead of kilometres
you’re never too smart
to make mistakes
[<Measure>]!
type Pence
e.g.! 42<Pence>!
! 153<Pence>!
! …
10<Meter> / 2<Second> ! = 5<Meter/Second>!
10<Meter> * 2<Second> ! = 20<Meter Second> !
10<Meter> + 10<Meter> ! = 20<Meter>!
10<Meter> * 10! ! ! = 100<Meter>!
10<Meter> * 10<Meter> ! = 100<Meter2>!
10<Meter> + 2<Second> ! // error!
10<Meter> + 2 ! ! ! // error
10<Meter> / 2<Second> ! = 5<Meter/Second>!
10<Meter> * 2<Second> ! = 20<Meter Second> !
10<Meter> + 10<Meter> ! = 20<Meter>!
10<Meter> * 10! ! ! = 100<Meter>!
10<Meter> * 10<Meter> ! = 100<Meter2>!
10<Meter> + 2<Second> ! // error!
10<Meter> + 2 ! ! ! // error
type Wager = int64<Pence>!
type Multiplier = int!
!
type Payout = Coins! of Wager!
! ! | MultipliedCoins of Multiplier * Wager!
! ! | Multi! of Payout list!
! ! | BonusGame
type Wager = int64<Pence>!
type Multiplier = int!
!
type Payout = Coins! of Wager!
! ! | MultipliedCoins of Multiplier * Wager!
! ! | Multi! of Payout list!
! ! | BonusGame
type Wager = int64<Pence>!
type Multiplier = int!
!
type Payout = Coins! of Wager!
! ! | MultipliedCoins of Multiplier * Wager!
! ! | Multi! of Payout list!
! ! | BonusGame
type State = !
{!
AvgWager! : Wager!
SpecialSymbol : Symbol!
Collectables : Map<Collectable, Count>!
}
New avg wager Got a Collectable!
A pay line win!
Betting small reduces avg wager!
Bonus Game!
type MonopolyBoardSpace = !
| RailRoad! ! of bool!
| Property! ! of int!
| ElectricCompany! of bool!
| WaterCompany! of bool!
| Chance! | CommunityChest!
| GotoJail! | Jail!
| FreeParking! | Go
type MonopolyBoardSpace = !
| RailRoad! ! of bool!
| Property! ! of int!
| ElectricCompany! of bool!
| WaterCompany! of bool!
| Chance! | CommunityChest!
| GotoJail! | Jail!
| FreeParking! | Go
type MonopolyBoardSpace = !
| RailRoad! ! of bool!
| Property! ! of int!
| ElectricCompany! of bool!
| WaterCompany! of bool!
| Chance! | CommunityChest!
| GotoJail! | Jail!
| FreeParking! | Go
type MonopolyBoardSpace = !
| RailRoad! ! of bool!
| Property! ! of int!
| ElectricCompany! of bool!
| WaterCompany! of bool!
| Chance! | CommunityChest!
| GotoJail! | Jail!
| FreeParking! | Go
[<Measure>]!
type Position!
!
type MonopolyBoard =!
{!
Spaces : MonopolyBoardSpace [ ]!
}!
member this.Item with !
get (pos : int<Position>) =!
this.Spaces.[int pos]
[<Measure>]!
type Position!
!
type MonopolyBoard =!
{!
Spaces : MonopolyBoardSpace [ ]!
}!
member this.Item with !
get (pos : int<Position>) = !
this.Spaces.[int pos]
And a pay line win!
Coin size brought over
from main game
Houses = multiplier on wins
GAME OVER
Collected in the bonus game.
Gives player extra ‘lives’.
type BonusGameState =!
{!
Board ! : MonopolyBoard!
Position ! : int<Position>!
Lives ! : int<Life>!
Doubles! : int<Double>!
CoinSize! : Wager!
TotalWin! : Wager!
}
Coin size brought over
from main game
type BonusGameState =!
{!
Board ! : MonopolyBoard!
Position ! : int<Position>!
Lives ! : int<Life>!
Doubles! : int<Double>!
CoinSize! : Wager!
TotalWin! : Wager!
}
And a pay line win!
Houses = multiplier on wins
type BonusGameState =!
{!
Board ! : MonopolyBoard!
Position ! : int<Position>!
Lives ! : int<Life>!
Doubles! : int<Double>!
CoinSize! : Wager!
TotalWin! : Wager!
}
Collected in the bonus game.
Gives player extra ‘lives’.
type BonusGameState =!
{!
Board ! : MonopolyBoard!
Position ! : int<Position>!
Lives ! : int<Life>!
Doubles! : int<Double>!
CoinSize! : Wager!
TotalWin! : Wager!
}
0<Position>
let jail = 6<Position>
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| RailRoad true ! -> awardRailRoadMultiplier state!
| Property n when n > 0 -> awardPropertyMultiplier n state!
| ElectricityCompany true!
| WaterCompany true -> awardUtilityMultiplier state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
…!
| CommunityChest! -> playCommunityChestCard state!
| Chance ! ! -> playChanceCard state!
…
let rec move newPos state =!
match state.Board.[newPos] with!
| RailRoad true ! -> awardRailRoadMultiplier state!
| Property n when n > 0 -> awardPropertyMultiplier n state!
| ElectricityCompany true!
| WaterCompany true -> awardUtilityMultiplier state!
| CommunityChest! -> playCommunityChestCard state!
| Chance ! ! -> playChanceCard state!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
| _ ! ! ! -> state
let rec move newPos state =!
match state.Board.[newPos] with!
| RailRoad true ! -> awardRailRoadMultiplier state!
| Property n when n > 0 -> awardPropertyMultiplier n state!
| ElectricityCompany true!
| WaterCompany true -> awardUtilityMultiplier state!
| CommunityChest! -> playCommunityChestCard state!
| Chance ! ! -> playChanceCard state!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
| _ ! ! ! -> state
let rec move newPos state =!
match state.Board.[newPos] with!
| RailRoad true ! -> awardRailRoadMultiplier state!
| Property n when n > 0 -> awardPropertyMultiplier n state!
| ElectricityCompany true!
| WaterCompany true -> awardUtilityMultiplier state!
| CommunityChest! -> playCommunityChestCard state!
| Chance ! ! -> playChanceCard state!
| GotoJail when state.Lives = 0<Life> -> !
! move jail state |> gameOver!
| GotoJail ! ! -> move jail state!
| _ ! ! ! -> state
Recap
lightweight syntax to
create types and
hierarchies
great for domain
modelling
make invalid states
unrepresentable
clear, concise way to
handle branching
better correctness
order of magnitude
increase in productivity
Stateful
Server
player states are big
Stateless Server DatabaseClient
1:1 read-write ratio
stateless = !
Inefficient & Expensive
ServerClient
Session 1
Session 2
ServerClient Database
Elastic Load Balancer
S3
Auto scaling Group
Server A Server B
...
EC2
CloudFront
Stateful Server
The Actor Model
An actor is the fundamental unit of computation
which embodies the 3 things!
• Processing!
• Storage!
• Communication!
that are essential to computation.!
!
-Carl Hewitt*
* http://bit.ly/HoNHbG
The Actor Model
• Everything is an actor!
• An actor has a mailbox!
• When an actor receives a message it can:!
– Create new actors!
– Send messages to actors!
– Designate how to handle the next message
Stateful Server
• Gatekeeper!
– Manages the local list of active workers!
– Spawns new workers!
!
• Worker!
– Manages the states for a player!
– Optimistic locking!
– Persist state after period of inactivity
Stateful Server
Game Server
Player A
Player B
S3
Worker C
Worker B
Gatekeeper
RequestHandlers
Asynchronous
Stateful Server
Game Server
Worker C
Worker B
Gatekeeper
Worker A
ok
RequestHandlers
Player A
Player B
Asynchronous
S3
Stateful Server
Game Server
S3
Worker C
Worker B
Gatekeeper
Worker A
RequestHandlers
Player A
Player B
Asynchronous
Stateful Server
Game Server
S3
Worker C
Gatekeeper
Worker A
RequestHandlers
Player A
Player B
Asynchronous
Stateful Server
Game Server
Worker C
Worker A
Gatekeeper
error
RequestHandlers
Player A
Player B
S3
Asynchronous
type Agent<‘T> = MailboxProcessor<‘T>!
!
!
!
type Agent<‘T> = MailboxProcessor<‘T>!
!
type Message = !
| Get of AsyncReplyChannel<…>!
| Put of State * Version * AsyncReplyChannel<…>
type Agent<‘T> = MailboxProcessor<‘T>!
!
type Message = !
| Get of AsyncReplyChannel<…>!
| Put of State * Version * AsyncReplyChannel<…>
type Result<‘T> =!
| Success! of ’T!
| Failure! of Exception!
!
!
!
type Result<‘T> =!
| Success! of ’T!
| Failure! of Exception!
!
type GetResult = Result<State * Version>!
type PutResult = Result<unit>!
type Agent<‘T> = MailboxProcessor<‘T>!
!
type Message = !
| Get of AsyncReplyChannel<GetResult>!
| Put of State * Version * AsyncReplyChannel<PutResult>
type Agent<‘T> = MailboxProcessor<‘T>!
!
type Message = !
| Get of AsyncReplyChannel<GetResult>!
| Put of State * Version * AsyncReplyChannel<PutResult>
type Worker (playerId) =!
let agent = Agent<Message>.Start(fun inbox ->!
let state = getCurrentState playerId!
!
let rec workingState (state, version) = !
async { … }!
and closedState () =!
async { … }!
!
workingState (state, 1))
type Worker (playerId) =!
let agent = Agent<Message>.Start(fun inbox ->!
let state = getCurrentState playerId!
!
let rec workingState (state, version) = !
async { … }!
and closedState () =!
async { … }!
!
workingState (state, 1))
type Worker (playerId) =!
let agent = Agent<Message>.Start(fun inbox ->!
let state = getCurrentState playerId!
!
let rec workingState (state, version) = !
async { … }!
and closedState () =!
async { … }!
!
workingState (state, 1))
type Worker (playerId) =!
let agent = Agent<Message>.Start(fun inbox ->!
let state = getCurrentState playerId!
!
let rec workingState (state, version) = !
async { … }!
and closedState () =!
async { … }!
!
workingState (state, 1))
type Worker (playerId) =!
let agent = Agent<Message>.Start(fun inbox ->!
let state = getCurrentState playerId!
!
let rec workingState (state, version) = !
async { … }!
and closedState () =!
async { … }!
!
workingState (state, 1))
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
| None -> !
do! persist state!
return! closedState()!
…!
}!
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
| None -> !
do! persist state!
return! closedState()!
…!
}!
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
| None -> !
do! persist state!
return! closedState()!
…!
}!
non-blocking I/O
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
| None -> !
do! persist state!
return! closedState()!
…!
}!
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
| None -> !
do! persist state!
return! closedState()!
…!
}!
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
…!
| Some(Get(reply)) ->!
reply.Reply <| Success(state, version)!
return! workingState(state, version)!
…!
}!
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
…!
| Some(Put(newState, v, reply)) when version = v ->!
reply.Reply <| Success()!
return! workingState(newState, version+1)!
…!
}
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
…!
| Some(Put(_, v, reply)) ->!
reply.Reply <| Failure(VersionMismatch(version, v))!
return! workingState(state, version)!
}
let rec workingState (state, version) = !
async { !
let! msg = inbox.TryReceive(60000)!
match msg with!
| None ! ! ! ! ! ! ! -> …!
| Some(Get(reply)) ! ! ! ! ! -> …!
| Some(Put(newState, v, reply)) when version = v ! -> …!
| Some(Put(_, v, reply)) ! ! ! ! -> …!
}
and closedState () = !
async { !
let! msg = inbox.Receive()!
match msg with!
| Get(reply) ->!
reply.Reply <| Failure(WorkerStopped)!
return! closedState()!
| Put(_, _, reply) ->!
reply.Reply <| Failure(WorkerStopped)!
return! closedState()!
}
and closedState () = !
async { !
let! msg = inbox.Receive()!
match msg with!
| Get(reply) ->!
reply.Reply <| Failure(WorkerStopped)!
return! closedState()!
| Put(_, _, reply) ->!
reply.Reply <| Failure(WorkerStopped)!
return! closedState()!
}
5x efficient
improvement
60% latency drop
no databases
need to ensure
server affinity
need to balance load
need to avoid
hotspots
• Persist player state after short inactivity!
• Move player to another server after persistence
need to gracefully
scale down
Recap
Agents!
• no locks!
• async message passing!
!
Agents!
• no locks!
• async message passing!
• self-contained!
• easy to reason with
Agents!
• low level!
• exceptions kills agents!
• primitive error monitoring!
• no supervision!
• no distribution
MS Orleans
Cricket
akka.Net
Async Workflow!
• non-blocking I/O!
• no callbacks
Pattern Matching!
• clear & concise
Replacing a
large
class
hierarchy
Caught a Gnome
EXP Item Gold
Quest Progress
Caught a Gnome
Level Up
Quest Progress
EXP Item Gold
Caught a Gnome
Quest Complete
Level Up
Quest Progress
EXP Item Gold
Caught a Gnome
New Quest
Quest Complete
Quest Progress
EXP Item Gold
Caught a Gnome
Quest Complete
New Quest
Level Up
Quest Progress
New Quest
Achievement
Progress
EXP Item Gold
Quest Complete
Level Up
Caught a Gnome
Level Up
Quest Progress
EXP Item Gold
Caught a Gnome
Quest Complete
New Quest
Achievement
Progress
Achievement
Complete
Level Up
Quest Progress
EXP Item Gold
Caught a Gnome
Quest Complete
New Quest
Achievement
Progress
Achievement
Complete
100+ actions
triggered by different
abstraction layers
non-functional
requirements
message-broker
pattern
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
Ignore
Process
Process
Process
Process
Ignore
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Process
Ignore
Ignore
Ignore
Process
Ignore
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Level Up
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Level Up
need lots of facts
type Fact =!
| GotExp! ! of Exp!
| GotGold! ! of Gold!
| GotItem! ! of Item * Count!
| CaughtMonster! of Monster * Bait * Location!
| LevelUp! ! of OldLevel * NewLevel!
…
type Reward =!
| GotExp! ! of Exp!
| GotGold! ! of Gold!
| GotItem! ! of Item * Count!
!
type StateChange =!
| LevelUp! ! of OldLevel * NewLevel!
…
type Fact =!
| StateChange! of StateChange!
| Reward! ! of Reward!
| Trapping! ! of Trapping!
| Fishing! ! of Fishing!
…
let process fact =!
match fact with!
| StateChange(stateChange)! -> …!
| Reward(reward)! ! ! -> …!
| Trapping(trapping)! ! -> …!
…
C# interop
…!
var fact = Fact.NewStateChange(!
! StateChange.NewLevelUp(oldLvl, newLvl));!
…
type IFact = interface end!
!
type Reward =!
| GotExp! ! of Exp!
| GotGold! ! of Gold!
| GotItem! ! of Item * Count!
interface IFact
type IFact = interface end!
!
type Reward =!
| GotExp! ! of Exp!
| GotGold! ! of Gold!
| GotItem! ! of Item * Count!
interface IFact
let process (fact : IFact) =!
match fact with!
| :? StateChange ! as stateChange!-> …!
| :? Reward ! ! as reward! ! -> …!
| :? Trapping! ! as trapping! -> …!
…!
| _ -> raise <| NotSupportedFact fact
let process (fact : IFact) =!
match fact with!
| :? StateChange ! as stateChange!-> …!
| :? Reward ! ! as reward! ! -> …!
| :? Trapping! ! as trapping! -> …!
…!
| _ -> raise <| NotSupportedFact fact
simple
flexible
extensible
saver
April 2015
Fri 8.30am, Salon H
@theburningmonk / theburningmonk.com
Fri 8.30am, Salon H
Fri 2.45pm, Guava + Tamarind
@theburningmonk / theburningmonk.com

More Related Content

What's hot

replacing `import` with `accio`
replacing `import` with `accio`replacing `import` with `accio`
replacing `import` with `accio`Amy Hanlon
 
Modelling Game Economy with Neo4j
Modelling Game Economy with Neo4jModelling Game Economy with Neo4j
Modelling Game Economy with Neo4jYan Cui
 
Async: ways to store state
Async:  ways to store stateAsync:  ways to store state
Async: ways to store statekao kuo-tung
 
An (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to PythonAn (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to PythonNicholas Tollervey
 
Rubyconf Bangladesh 2017 - Lets start coding in Ruby
Rubyconf Bangladesh 2017 - Lets start coding in RubyRubyconf Bangladesh 2017 - Lets start coding in Ruby
Rubyconf Bangladesh 2017 - Lets start coding in RubyRuby Bangladesh
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubyJason Yeo Jie Shun
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosEdgar Suarez
 

What's hot (7)

replacing `import` with `accio`
replacing `import` with `accio`replacing `import` with `accio`
replacing `import` with `accio`
 
Modelling Game Economy with Neo4j
Modelling Game Economy with Neo4jModelling Game Economy with Neo4j
Modelling Game Economy with Neo4j
 
Async: ways to store state
Async:  ways to store stateAsync:  ways to store state
Async: ways to store state
 
An (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to PythonAn (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to Python
 
Rubyconf Bangladesh 2017 - Lets start coding in Ruby
Rubyconf Bangladesh 2017 - Lets start coding in RubyRubyconf Bangladesh 2017 - Lets start coding in Ruby
Rubyconf Bangladesh 2017 - Lets start coding in Ruby
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in Ruby
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
 

Viewers also liked

Tour of language landscape (katsconf)
Tour of language landscape (katsconf)Tour of language landscape (katsconf)
Tour of language landscape (katsconf)Yan Cui
 
F# in the cloud
F# in the cloudF# in the cloud
F# in the cloudYan Cui
 
F# in social gaming
F# in social gamingF# in social gaming
F# in social gamingYan Cui
 
My adventure with elm (LambdaCon15)
My adventure with elm (LambdaCon15)My adventure with elm (LambdaCon15)
My adventure with elm (LambdaCon15)Yan Cui
 
BigQuery in Social Gaming
BigQuery in Social GamingBigQuery in Social Gaming
BigQuery in Social GamingYan Cui
 
Introduction to Aspect Oriented Programming (DDD South West 4.0)
Introduction to Aspect Oriented Programming (DDD South West 4.0)Introduction to Aspect Oriented Programming (DDD South West 4.0)
Introduction to Aspect Oriented Programming (DDD South West 4.0)Yan Cui
 
Tour of language landscape (code.talks)
Tour of language landscape (code.talks)Tour of language landscape (code.talks)
Tour of language landscape (code.talks)Yan Cui
 
My adventure with Elm
My adventure with ElmMy adventure with Elm
My adventure with ElmYan Cui
 
Tour of language landscape
Tour of language landscapeTour of language landscape
Tour of language landscapeYan Cui
 
The future of paas is serverless
The future of paas is serverlessThe future of paas is serverless
The future of paas is serverlessYan Cui
 
Fear and loathing with APL (oredev)
Fear and loathing with APL (oredev)Fear and loathing with APL (oredev)
Fear and loathing with APL (oredev)Yan Cui
 
Tour of language landscape
Tour of language landscapeTour of language landscape
Tour of language landscapeYan Cui
 
AWS Lambda from the Trenches
AWS Lambda from the TrenchesAWS Lambda from the Trenches
AWS Lambda from the TrenchesYan Cui
 
Modelling game economy with Neo4j
Modelling game economy with Neo4jModelling game economy with Neo4j
Modelling game economy with Neo4jYan Cui
 
Build reactive systems on lambda
Build reactive systems on lambdaBuild reactive systems on lambda
Build reactive systems on lambdaYan Cui
 
F# in the real world (NDC)
F# in the real world (NDC)F# in the real world (NDC)
F# in the real world (NDC)Yan Cui
 

Viewers also liked (16)

Tour of language landscape (katsconf)
Tour of language landscape (katsconf)Tour of language landscape (katsconf)
Tour of language landscape (katsconf)
 
F# in the cloud
F# in the cloudF# in the cloud
F# in the cloud
 
F# in social gaming
F# in social gamingF# in social gaming
F# in social gaming
 
My adventure with elm (LambdaCon15)
My adventure with elm (LambdaCon15)My adventure with elm (LambdaCon15)
My adventure with elm (LambdaCon15)
 
BigQuery in Social Gaming
BigQuery in Social GamingBigQuery in Social Gaming
BigQuery in Social Gaming
 
Introduction to Aspect Oriented Programming (DDD South West 4.0)
Introduction to Aspect Oriented Programming (DDD South West 4.0)Introduction to Aspect Oriented Programming (DDD South West 4.0)
Introduction to Aspect Oriented Programming (DDD South West 4.0)
 
Tour of language landscape (code.talks)
Tour of language landscape (code.talks)Tour of language landscape (code.talks)
Tour of language landscape (code.talks)
 
My adventure with Elm
My adventure with ElmMy adventure with Elm
My adventure with Elm
 
Tour of language landscape
Tour of language landscapeTour of language landscape
Tour of language landscape
 
The future of paas is serverless
The future of paas is serverlessThe future of paas is serverless
The future of paas is serverless
 
Fear and loathing with APL (oredev)
Fear and loathing with APL (oredev)Fear and loathing with APL (oredev)
Fear and loathing with APL (oredev)
 
Tour of language landscape
Tour of language landscapeTour of language landscape
Tour of language landscape
 
AWS Lambda from the Trenches
AWS Lambda from the TrenchesAWS Lambda from the Trenches
AWS Lambda from the Trenches
 
Modelling game economy with Neo4j
Modelling game economy with Neo4jModelling game economy with Neo4j
Modelling game economy with Neo4j
 
Build reactive systems on lambda
Build reactive systems on lambdaBuild reactive systems on lambda
Build reactive systems on lambda
 
F# in the real world (NDC)
F# in the real world (NDC)F# in the real world (NDC)
F# in the real world (NDC)
 

Similar to F# in social gaming (CodeMash 15)

ViewController/State
ViewController/StateViewController/State
ViewController/Stategillygize
 
HadoopとMongoDBを活用したソーシャルアプリのログ解析
HadoopとMongoDBを活用したソーシャルアプリのログ解析HadoopとMongoDBを活用したソーシャルアプリのログ解析
HadoopとMongoDBを活用したソーシャルアプリのログ解析Takahiro Inoue
 
Tsi challenger-overview-copy[1]
Tsi challenger-overview-copy[1]Tsi challenger-overview-copy[1]
Tsi challenger-overview-copy[1]jeff dorsey
 
Short Term Risk From Long Term Models
Short Term Risk From Long Term ModelsShort Term Risk From Long Term Models
Short Term Risk From Long Term ModelsDickGlidden
 
F# in social gaming by Yan Cui at Codemotion Dubai
F# in social gaming by Yan Cui at Codemotion DubaiF# in social gaming by Yan Cui at Codemotion Dubai
F# in social gaming by Yan Cui at Codemotion DubaiCodemotion Dubai
 

Similar to F# in social gaming (CodeMash 15) (6)

ViewController/State
ViewController/StateViewController/State
ViewController/State
 
HadoopとMongoDBを活用したソーシャルアプリのログ解析
HadoopとMongoDBを活用したソーシャルアプリのログ解析HadoopとMongoDBを活用したソーシャルアプリのログ解析
HadoopとMongoDBを活用したソーシャルアプリのログ解析
 
Tsi challenger-overview-copy[1]
Tsi challenger-overview-copy[1]Tsi challenger-overview-copy[1]
Tsi challenger-overview-copy[1]
 
Short Term Risk From Long Term Models
Short Term Risk From Long Term ModelsShort Term Risk From Long Term Models
Short Term Risk From Long Term Models
 
F# in social gaming by Yan Cui at Codemotion Dubai
F# in social gaming by Yan Cui at Codemotion DubaiF# in social gaming by Yan Cui at Codemotion Dubai
F# in social gaming by Yan Cui at Codemotion Dubai
 
Fáessa
FáessaFáessa
Fáessa
 

More from Yan Cui

How to win the game of trade-offs
How to win the game of trade-offsHow to win the game of trade-offs
How to win the game of trade-offsYan Cui
 
How to choose the right messaging service
How to choose the right messaging serviceHow to choose the right messaging service
How to choose the right messaging serviceYan Cui
 
How to choose the right messaging service for your workload
How to choose the right messaging service for your workloadHow to choose the right messaging service for your workload
How to choose the right messaging service for your workloadYan Cui
 
Patterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdfPatterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdfYan Cui
 
Lambda and DynamoDB best practices
Lambda and DynamoDB best practicesLambda and DynamoDB best practices
Lambda and DynamoDB best practicesYan Cui
 
Lessons from running AppSync in prod
Lessons from running AppSync in prodLessons from running AppSync in prod
Lessons from running AppSync in prodYan Cui
 
Serverless observability - a hero's perspective
Serverless observability - a hero's perspectiveServerless observability - a hero's perspective
Serverless observability - a hero's perspectiveYan Cui
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functionsYan Cui
 
How serverless changes the cost paradigm
How serverless changes the cost paradigmHow serverless changes the cost paradigm
How serverless changes the cost paradigmYan Cui
 
Why your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSyncWhy your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSyncYan Cui
 
Build social network in 4 weeks
Build social network in 4 weeksBuild social network in 4 weeks
Build social network in 4 weeksYan Cui
 
Patterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applicationsPatterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applicationsYan Cui
 
How to bring chaos engineering to serverless
How to bring chaos engineering to serverlessHow to bring chaos engineering to serverless
How to bring chaos engineering to serverlessYan Cui
 
Migrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 stepsMigrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 stepsYan Cui
 
Building a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQLBuilding a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQLYan Cui
 
FinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economyFinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economyYan Cui
 
How to improve lambda cold starts
How to improve lambda cold startsHow to improve lambda cold starts
How to improve lambda cold startsYan Cui
 
What can you do with lambda in 2020
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020Yan Cui
 
A chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage awayA chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage awayYan Cui
 
How to debug slow lambda response times
How to debug slow lambda response timesHow to debug slow lambda response times
How to debug slow lambda response timesYan Cui
 

More from Yan Cui (20)

How to win the game of trade-offs
How to win the game of trade-offsHow to win the game of trade-offs
How to win the game of trade-offs
 
How to choose the right messaging service
How to choose the right messaging serviceHow to choose the right messaging service
How to choose the right messaging service
 
How to choose the right messaging service for your workload
How to choose the right messaging service for your workloadHow to choose the right messaging service for your workload
How to choose the right messaging service for your workload
 
Patterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdfPatterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdf
 
Lambda and DynamoDB best practices
Lambda and DynamoDB best practicesLambda and DynamoDB best practices
Lambda and DynamoDB best practices
 
Lessons from running AppSync in prod
Lessons from running AppSync in prodLessons from running AppSync in prod
Lessons from running AppSync in prod
 
Serverless observability - a hero's perspective
Serverless observability - a hero's perspectiveServerless observability - a hero's perspective
Serverless observability - a hero's perspective
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functions
 
How serverless changes the cost paradigm
How serverless changes the cost paradigmHow serverless changes the cost paradigm
How serverless changes the cost paradigm
 
Why your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSyncWhy your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSync
 
Build social network in 4 weeks
Build social network in 4 weeksBuild social network in 4 weeks
Build social network in 4 weeks
 
Patterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applicationsPatterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applications
 
How to bring chaos engineering to serverless
How to bring chaos engineering to serverlessHow to bring chaos engineering to serverless
How to bring chaos engineering to serverless
 
Migrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 stepsMigrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 steps
 
Building a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQLBuilding a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQL
 
FinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economyFinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economy
 
How to improve lambda cold starts
How to improve lambda cold startsHow to improve lambda cold starts
How to improve lambda cold starts
 
What can you do with lambda in 2020
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020
 
A chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage awayA chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage away
 
How to debug slow lambda response times
How to debug slow lambda response timesHow to debug slow lambda response times
How to debug slow lambda response times
 

Recently uploaded

Kuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialKuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialJoão Esperancinha
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...itnewsafrica
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Karmanjay Verma
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFMichael Gough
 
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sectoritnewsafrica
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...amber724300
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...BookNet Canada
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 

Recently uploaded (20)

Kuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialKuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorial
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDF
 
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 

F# in social gaming (CodeMash 15)