SlideShare a Scribd company logo
tame
|> (cloud <| complexity)
|> with
|> (fsharp >> powered >> DSLs)
hi,I’mYanCui
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
AWS user since 2009
Tame cloud complexity with F# powered DSLs (build stuff)
image by nerovivo license : https://creativecommons.org/licenses/by-sa/2.0/
Under-Abstraction
Oversimplification
Impedance Mismatch
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
F# DSLs. Awesome!
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
Tame cloud complexity with F# powered DSLs (build stuff)
managed
key-value store
redundancy
9-9s guarantee
great performance
name your
throughput
Tame cloud complexity with F# powered DSLs (build stuff)
can be changed on-the-fly
Tame cloud complexity with F# powered DSLs (build stuff)
infinitely scalable
(but you still have to pay for it)
Tame cloud complexity with F# powered DSLs (build stuff)
Hash Key
Range Key
Query:
given a hash key
filter on
range key, or
local secondary index
Tame cloud complexity with F# powered DSLs (build stuff)
Hash Key Range Key
Local Secondary Index
Global Secondary Index
Scan:
FULL TABLE search
(performance + cost concern)
Tame cloud complexity with F# powered DSLs (build stuff)
Hash Key Range Key
Local Secondary Index
Global Secondary Index
Hash Key Range Key
Local Secondary Index
Who are the TOP 3 players in “Starship
X” with a score of at least 1000?
Global Secondary Index
Tame cloud complexity with F# powered DSLs (build stuff)
select GameTitle, UserId, TopScore
from GameScores
where GameTitle = “Starship X”
and TopScore >= 1000
order desc
limit 3
with (NoConsistentRead, Index(GameTitleIndex, true))
DynamoDB.SQL
github.com/fsprojects/DynamoDb.SQL
GOAL
Disguise
complexity
GOAL
Prevent
abstraction leak
GOAL
SELECT UserId, TopScore
FROM GameScore
WHERE GameTitle CONTAINS “Zelda”
ORDER DESC
LIMIT 3
WITH (NoConsistentRead)
Query
AST
Execution
F# & FParsec*
*www.quanttec.com/fparsec
External DSL
via
Tame cloud complexity with F# powered DSLs (build stuff)
SELECT * FROM GameScore
Abstract Syntax Tree (AST)
FParsec
SELECT * FROM GameScore
keyword keyword
* | attribute, attribute, …
table name
SELECT * FROM GameScore
type Attributes =
| Asterisk
| Attributes of string[]
SELECT * FROM GameScore
type Query =
{
Attributes : Attributes
Table : string
}
SELECT * FROM GameScore
Parser for “SELECT” keyword
pSelect
SELECT * FROM GameScore
pSelect
let pSelect = skipStringCI "select"
SELECT * FROM GameScore
pSelect
let pSelect = skipStringCI "select"
matches the string “select” (Case
Insensitive) and ignores it
SELECT * FROM GameScore
pFrom
let pFrom = skipStringCI "from"
SELECT * FROM GameScore
Parser for a string that
represents the table name
pTableName
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
parses a sequence of one or
more chars that satisfies the
predicate function
SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let pAsterisk = stringCIReturn "*" Asterisk
SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let pAsterisk = stringCIReturn "*" Asterisk
matches the specified string
and return the given value
SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let isAttributeName = isLetter <||> isDigit
let pAttributeName =
many1Satisfy isAttributeName
SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pComma = skipStringCI ","
SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pAttributeNames =
sepBy1 pAttributeName pComma
SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pAttributeNames =
sepBy1 pAttributeName pComma
parses one or more occurrences of
pAttributeName separated by pComma
SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pComma
sepBy1
pAttributeNames
pAsterisk
*
SELECT * FROM GameScore
pAsterisk
*
pAttributeNames
UserId, GameTitle, TopScore, …
SELECT * FROM GameScore
pAsterisk
*
pAttributeNames
UserId, GameTitle, TopScore, …
let pAttribute =
pAsterisk <|> pAttributeNames
SELECT * FROM GameScore
pAsterisk
*
pAttributeNames
UserId, GameTitle, TopScore, …
let pAttribute =
pAsterisk <|> pAttributeNames
SELECT * FROM GameScore
pAsterisk
*
pAttributeNames
UserId, GameTitle, TopScore, …
choice
pAttribute
SELECT * FROM GameScore
pAttribute
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
let pQuery =
tuple4 pSelect pAttribute
pFrom pTableName
|>> (fun (_, attributes, _, table) ->
{ Attributes = attributes
Table = table })
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
let pQuery =
tuple4 pSelect pAttribute
pFrom pTableName
|>> (fun (_, attributes, _, table) ->
{ Attributes = attributes
Table = table })
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
let pQuery =
tuple4 pSelect pAttribute
pFrom pTableName
|>> (fun (_, attributes, _, table) ->
{ Attributes = attributes
Table = table })
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
let pQuery =
tuple4 pSelect pAttribute
pFrom pTableName
|>> (fun (_, attributes, _, table) ->
{ Attributes = attributes
Table = table })
Query
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
tuple4
pQuery
Tame cloud complexity with F# powered DSLs (build stuff)
< 50 lines of code
Amazing
F# + FParsec
=
Recap
Tame cloud complexity with F# powered DSLs (build stuff)
select GameTitle, UserId, TopScore
from GameScores
where GameTitle = “Starship X”
and TopScore >= 1000
order desc
limit 3
with (NoConsistentRead, Index(GameTitleIndex, true))
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
Tame cloud complexity with F# powered DSLs (build stuff)
Decision Worker
Decision Worker
Poll
Decision Worker
Decision
Task
Decision WorkerDecide
Activity Worker
Decision Worker
Activity Worker
Decision Worker
Poll
Activity Worker
Decision Worker
Activity
Task
Activity Worker
Decision Worker
Complete
Workers can run from
anywhere
Tame cloud complexity with F# powered DSLs (build stuff)
input = “Yan”
result = “Hello Yan!”
Start
Finish
Activity
Tame cloud complexity with F# powered DSLs (build stuff)
image by Ryan Hageman license : https://creativecommons.org/licenses/by-sa/2.0/
SWF-based Application
API
Heartbeats
Error
Handling
Polling
API
Activity
Worker
Decision
Worker
Heartbeats
Error
Handling
Polling
API
Activity
Worker
Decision
Worker
Heartbeats
Error
Handling
Polling
API
Boilerplate
– Kris Jordan
“Good simplicity is less with
leverage, not less with less.
Good simplicity is complexity
disguised, not complexity denied.”
http://bit.ly/1pOLeKl
Tame cloud complexity with F# powered DSLs (build stuff)
Start
Finish
Activity
?
the workflow is
implied by decision
worker logic…
instead..
the workflow should
drive decision
worker logic
the workflow should
driveautomate
decision worker logic
Amazon
.SimpleWorkflow
.Extensions
github.com/fsprojects/Amazon.SimpleWorkflow.Extensions
GOAL
Remove
boilerplates
GOAL
Code that matches
the way you think
Start
Finish
Activity
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
Start
Finish
Activity
Tame cloud complexity with F# powered DSLs (build stuff)
Workflows can be
nested
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
input
result
Tame cloud complexity with F# powered DSLs (build stuff)
Recap
Activity
Worker
Decision
Worker
Heartbeats
Error
Handling
Polling
API
Tame cloud complexity with F# powered DSLs (build stuff)
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
wanna find
correlations?
wanna find
correlations?
you can DIY it!
;-)
“what latencies spiked
at the same time as
payment service?”
Amazon
.CloudWatch
.Selector
github.com/fsprojects/Amazon.CloudWatch.Selector
Find metrics whose 5
min average exceeded
1 second during last
12 hours
cloudWatch.Select(
unitIs “milliseconds” +
average (>) 1000.0
@ last 12 hours
|> intervalOf 5 minutes)
cloudWatch.Select(“
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes”)
“did any cache
nodes’ CPU spike
yesterday?”
cloudWatch.Select(
namespaceLike “elasticache” +
nameLike “cpu” +
max (>) 80.0
@ last 24 hours
|> intervalOf 15 minutes)
cloudWatch.Select(
namespaceLike “elasticache” +
nameLike “cpu” +
max (>) 80.0
@ last 24 hours
|> intervalOf 15 minutes)
Regex
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
Filters
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
TimeFrame
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
Period
type Query =
{
Filter : Filter
TimeFrame : TimeFrame
Period : Period option
}
Query
Internal
DSL
External
DSL
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
type MetricTerm = Namespace | Name
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
type MetricTerm = Namespace | Name
type Unit = | Unit
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
| UnitFilter of Unit * (string -> bool)
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
type MetricTerm = Namespace | Name
type Unit = | Unit
type StatsTerm =
| Average | Min | Max | Sum | SampleCount
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
| UnitFilter of Unit * (string -> bool)
| StatsFilter of StatsTerm * (float -> bool)
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
type MetricTerm = Namespace | Name
type Unit = | Unit
type StatsTerm =
| Average | Min | Max | Sum | SampleCount
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
| UnitFilter of Unit * (string -> bool)
| StatsFilter of StatsTerm * (float -> bool)
| CompositeFilter of Filter * Filter
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
type TimeFrame =
| Last of TimeSpan
| Since of DateTime
| Between of DateTime * DateTime
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
type Period = | Period of TimeSpan
type Query =
{
Filter : Filter
TimeFrame : TimeFrame
Period : Period option
}
Active Patterns
a primer on
allow patterns to be
abstracted away into
named functions
Single-Case Patterns
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
Float : string -> float
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
match “42” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
match “boo” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
Error!!!
Partial Patterns
let (|Float|_|) input =
match Double.TryParse input with
| true, n -> Some n
| _ -> None
let (|Float|_|) input =
match Double.TryParse input with
| true, n -> Some n
| _ -> None
Float : string -> float option
match “boo” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
| _ -> “not a float”
match “boo” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
| _ -> “not a float”
Multi-Case Patterns
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
match someString with
| Prime n -> …
| NotPrime n -> …
| NaN -> …
match someString with
| Prime n & Float 11.0 -> …
| Prime n -> …
| Float 42.0 | Float 8.0 -> …
| NotPrime n -> …
| NaN -> …
match someString with
| Prime n & Float 11.0 -> …
| Prime n -> …
| Float 42.0 | Float 8.0 -> …
| NotPrime n -> …
| NaN -> …
match someString with
| Prime (IsPalindrome n) -> …
| Prime (IsEven n) -> …
| _ -> …
Tokenise
(string -> string list)
[
“namespaceIs”; “‘JustEat’”; “and”;
“nameLike”; “‘cpu’”; “and”;
…
]
“namespaceIs” “and” …
F# List = LinkedList
“‘JustEat’”
“namespaceIs” “and” …
F# List = LinkedList
“namespaceIs” “‘JustEat’” “and”:::: :: tail
cons (::) operator to prepend
“‘JustEat’”
“namespaceIs” “and” …
F# List = LinkedList
“namespaceIs” “‘JustEat’” “and”:::: :: tail
match aList with
|
“‘JustEat’”
works as a pattern too!
let (|StringCI|_|) (str : string) (input : string) =
if str.ToLower() = input.ToLower()
then Some ()
else None
let (|Float|_|) input =
match System.Double.TryParse input with
| true, n -> Some n
| _ -> None
let (|EmptyString|_|) input =
if String.IsNullOrWhiteSpace input
then Some ()
else None
let (|StartsWith|_|) char (input : string) =
if input.[0] = char then Some () else None
let (|EndsWith|_|) char (input : string) =
if input.[input.Length-1] = char
then Some ()
else None
let (|QuotedString|_|) (input : string) =
match input with
| EmptyString -> None
| str when str.Length < 2 -> None
| StartsWith ''' & EndsWith ''' ->
Some <| input.Substring(1, input.Length - 2)
| _ -> None
let (|QuotedString|_|) (input : string) =
match input with
| EmptyString -> None
| str when str.Length < 2 -> None
| StartsWith ''' & EndsWith ''' ->
Some <| input.Substring(1, input.Length - 2)
| _ -> None
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
…
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
“namespaceIs” “‘JustEat’” :::: …
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
type MetricTerm = Namespace | Name
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
“and” :: “nameLike” :: “‘cpu’” :: “and” :: …
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
let parse (input : string) =
input
|> tokenize
|> parseFilter
|> parseTimeFrame
|> parsePeriod
Amazing
F#
=
usable from anywhere you
can run F# code
e.g. F# REPL, executable, ..
Internal DSL
useful for building tools
e.g. CLI, …
External DSL
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
Recap
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
@theburningmonk
theburningmonk.com
github.com/theburningmonk

More Related Content

PPT
Introduction to PowerShell
PPTX
Windows PowerShell
PDF
Node Boot Camp
PPT
PowerShell Technical Overview
PPTX
Powershell Tech Ed2009
PDF
Introducing Elixir and OTP at the Erlang BASH
PDF
React Native Evening
KEY
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
Introduction to PowerShell
Windows PowerShell
Node Boot Camp
PowerShell Technical Overview
Powershell Tech Ed2009
Introducing Elixir and OTP at the Erlang BASH
React Native Evening
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard

What's hot (20)

PDF
Introduction to Elixir
PDF
Refactoring Infrastructure Code
PDF
Hello elixir (and otp)
PDF
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
PDF
Concurrecny inf sharp
PDF
What's New in ES6 for Web Devs
PDF
Actor Clustering with Docker Containers and Akka.Net in F#
PDF
Rack Middleware
PDF
ssh.isdn.test
PDF
InterConnect: Server Side Swift for Java Developers
ODP
Modern Perl
PDF
Bootstrap |> Elixir - Easy fun for busy developers
PDF
Origins of Elixir programming language
ODP
using python module: doctest
PDF
Fabric Python Lib
PPTX
PDF
InterConnect: Java, Node.js and Swift - Which, Why and When
PDF
Phoenix for Rails Devs
PDF
Hopping in clouds: a tale of migration from one cloud provider to another
PPTX
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
Introduction to Elixir
Refactoring Infrastructure Code
Hello elixir (and otp)
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
Concurrecny inf sharp
What's New in ES6 for Web Devs
Actor Clustering with Docker Containers and Akka.Net in F#
Rack Middleware
ssh.isdn.test
InterConnect: Server Side Swift for Java Developers
Modern Perl
Bootstrap |> Elixir - Easy fun for busy developers
Origins of Elixir programming language
using python module: doctest
Fabric Python Lib
InterConnect: Java, Node.js and Swift - Which, Why and When
Phoenix for Rails Devs
Hopping in clouds: a tale of migration from one cloud provider to another
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09

Similar to Tame cloud complexity with F# powered DSLs (build stuff) (20)

PDF
Tame Cloud Complex with F# powered DSLs
PDF
Tame cloud complexity with F#-powered DSLs
PPTX
Database Management System Review
PDF
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
PDF
MongoDB .local Houston 2019:Tips and Tricks++ for Querying and Indexing MongoDB
PDF
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing Mo...
PDF
PDF
KScope19 - SQL Features
PDF
Dbms narrative question answers
ZIP
Postgres is easier
PDF
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
PDF
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
PDF
01Query Processing and Optimization-SUM25.pdf
PDF
JDD 2016 - Tomasz Borek - DB for next project? Why, Postgres, of course
PPTX
Gymkhana management system
PPTX
SQL Server Select Topics
PDF
Postgresql 9.3 overview
PPTX
SQL techniques for faster applications
PDF
UKOUG 2019 - SQL features
PDF
MongoDB World 2019: Tips and Tricks++ for Querying and Indexing MongoDB
Tame Cloud Complex with F# powered DSLs
Tame cloud complexity with F#-powered DSLs
Database Management System Review
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local Houston 2019:Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing Mo...
KScope19 - SQL Features
Dbms narrative question answers
Postgres is easier
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
01Query Processing and Optimization-SUM25.pdf
JDD 2016 - Tomasz Borek - DB for next project? Why, Postgres, of course
Gymkhana management system
SQL Server Select Topics
Postgresql 9.3 overview
SQL techniques for faster applications
UKOUG 2019 - SQL features
MongoDB World 2019: Tips and Tricks++ for Querying and Indexing MongoDB

More from Yan Cui (20)

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

Recently uploaded (20)

PDF
Encapsulation theory and applications.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Electronic commerce courselecture one. Pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PPTX
Spectroscopy.pptx food analysis technology
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Unlocking AI with Model Context Protocol (MCP)
Encapsulation theory and applications.pdf
Spectral efficient network and resource selection model in 5G networks
20250228 LYD VKU AI Blended-Learning.pptx
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
MYSQL Presentation for SQL database connectivity
Network Security Unit 5.pdf for BCA BBA.
Dropbox Q2 2025 Financial Results & Investor Presentation
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Electronic commerce courselecture one. Pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
Advanced methodologies resolving dimensionality complications for autism neur...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
MIND Revenue Release Quarter 2 2025 Press Release
Per capita expenditure prediction using model stacking based on satellite ima...
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
NewMind AI Weekly Chronicles - August'25 Week I
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Spectroscopy.pptx food analysis technology
The Rise and Fall of 3GPP – Time for a Sabbatical?
Unlocking AI with Model Context Protocol (MCP)

Tame cloud complexity with F# powered DSLs (build stuff)