The emergence of Cloud platforms has fundamentally changed the IT landscape. However, attempting to ride on this ever-expanding platform ecosystem wave has created a new set of challenges.
Join Yan Cui in this talk as he draws on his extensive experience with AWS over the last 7 years to illustrate, with real-world use examples, how you can use F# to build internal and external DSLs to tame the complexity from these cloud services.
31. Hash Key Range Key
Local Secondary Index
Global Secondary Index
32. 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
33.
34. select GameTitle, UserId, TopScore
from GameScores
where GameTitle = “Starship X”
and TopScore >= 1000
order desc
limit 3
with (NoConsistentRead, Index(GameTitleIndex, true))
42. SELECT * FROM GameScore
Abstract Syntax Tree (AST)
FParsec
43. SELECT * FROM GameScore
keyword keyword
* | attribute, attribute, …
table name
44. SELECT * FROM GameScore
type Attributes =
| Asterisk
| Attributes of string[]
45. SELECT * FROM GameScore
type Query =
{
Attributes : Attributes
Table : string
}
46. SELECT * FROM GameScore
Parser for “SELECT” keyword
pSelect
47. SELECT * FROM GameScore
pSelect
let pSelect = skipStringCI "select"
48. SELECT * FROM GameScore
pSelect
let pSelect = skipStringCI "select"
matches the string “select” (Case
Insensitive) and ignores it
49. SELECT * FROM GameScore
pFrom
let pFrom = skipStringCI "from"
50. SELECT * FROM GameScore
Parser for a string that
represents the table name
pTableName
51. SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
52. SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
53. SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
54. SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
55. 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
57. SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let pAsterisk = stringCIReturn "*" Asterisk
58. SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let pAsterisk = stringCIReturn "*" Asterisk
matches the specified string
and return the given value
59. SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let isAttributeName = isLetter <||> isDigit
let pAttributeName =
many1Satisfy isAttributeName
60. SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pComma = skipStringCI ","
61. SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pAttributeNames =
sepBy1 pAttributeName pComma
62. SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pAttributeNames =
sepBy1 pAttributeName pComma
parses one or more occurrences of
pAttributeName separated by pComma
80. select GameTitle, UserId, TopScore
from GameScores
where GameTitle = “Starship X”
and TopScore >= 1000
order desc
limit 3
with (NoConsistentRead, Index(GameTitleIndex, true))
150. type MetricTerm = Namespace | Name
type Unit = | Unit
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
| UnitFilter of Unit * (string -> bool)
152. 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)
154. 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
163. let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
164. let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
165. let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
Float : string -> float
166. match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
167. 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
168. 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
169. 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
170. 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
171. match “42” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
172. match “boo” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
Error!!!
191. “namespaceIs” “and” …
F# List = LinkedList
“namespaceIs” “‘JustEat’” “and”:::: :: tail
cons (::) operator to prepend
“‘JustEat’”
192. “namespaceIs” “and” …
F# List = LinkedList
“namespaceIs” “‘JustEat’” “and”:::: :: tail
match aList with
|
“‘JustEat’”
works as a pattern too!
193. 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
194. 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
195. 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
196. 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
197. let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
198. let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
…
199. let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
“namespaceIs” “‘JustEat’” :::: …
200. 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)