Share
Embed
Hack_n_Learn_Fsharp_Ajira
My workshop slides for the event https://www.meetup.com/Hack-Learn/events/232941739/
Tamizhvendan S
August 27, 2016
Transcript
40 slides
-
F# F# is a mature, open source, cross-platform, functional-first programming
language. It empowers users and organizations to tackle complex computing problems with simple, maintainable and robust code. - http://fsharp.org/ -
Functional Programming >> >=> >>= << |> Define “System” by
composing functions -
POST /message Chat Server CREATE Model Your Domain HttpRequest Message
Error Result<Message,Error> HttpResponse x -
POST /message Chat Server CREATE Define functions readRequest :: HttpRequest
-> Result<Message,Error> validate :: Message -> Result<Message,Error> createInDb :: Message -> Result<Message,Error> writeResponse :: Result<Message,Error> -> HttpResponse λx -
POST /message Chat Server CREATE Compose functions readRequest >>= validate
>>= createInDb |> writeResponse system :: HttpRequest -> HttpResponse -
Step 1 Model HttpMethod Get, Put, Post type Color =
Red | Green | Blue -
Step 2 Model Request Request contains HttpMethod & Path type
Rectangle = { Color : Color Height : double Width : double } Whitespace is significant -
Step 3 Model StatusCode Ok, NotFound, BadRequest type Color =
Red | Green | Blue -
Step 4 Define toStatusCode function to return StatusCode as integer
let toHex color = match color with | Red -> "#ff0000" | Green -> "#00ff00" | Blue -> "#0000ff" Last expression is the return of the function -
Step 5 Model Response Response contains StatusCode & Content type
Circle = { Color : Color Radius : double } -
Step 6 Model Context Context contains Request & Response type
Shape = { Rectangle : Rectangle Circle : Circle } -
Step 7 Model Handler Handler takes a context and may
return the (modified) context. type Handler = Shape -> Shape option A type can represent a function signature -
Step 8 Define OK Handler OK is a function that
takes a string and a Context It modifies the Response content with the string passed and sets the status code to Ok It returns the modified context as optional type let RADIUS radius shape = let circle = { Color = Red Radius = radius } {shape with Circle = circle} Records are immutable string -> Context -> Context option -
Step 9 Define ConsoleWriter let ConsoleWriter ctx handler = match
handler ctx with | Some ctx -> ctx.Response.StatusCode |> toStatusCode |> printfn "StatusCode: %d" printfn "Content : %s" ctx.Response.Content | None -> printfn "Empty" -
Let’s Play console (OK "test");; console <| OK "test";; fsharpi
—use:test.fsx fsi —use:test.fsx Use #q;; to Exit -
Step 10 Define NOT_FOUND Handler NOT_FOUND is a function that
takes a string and a Context It modifies the Response content with the string passed and sets the status code to NotFound It returns the modified context as optional type -
Step 11 Define BAD_REQUEST Handler BAD_REQUEST is a function that
takes a string and a Context It modifies the Response content with the string passed and sets the status code to BadRequest It returns the modified context as optional type -
Step 12 Let’s Refactor All handlers takes a content and
modifies the response let responseHandler statusCode content ctx = let res = {StatusCode = statusCode; Content = content} Some {ctx with Response = res} let OK = responseHandler Ok -
Step 13 Define GET (Filter)Handler GET verifies the HttpMethod of
the context’s Request It returns the context if it is Get else returns None Pattern Matching against booleans Context -> Context option let SQUARE shape = let rect = shape.Rectangle match rect.Height = rect.Width with | true -> Some shape | _ -> None -
Step 14 Define POST (Filter)Handler POST verifies the HttpMethod of
the context’s Request It returns the context if it is Post else returns None Context -> Context option -
Step 15 Define PUT (Filter)Handler PUT verifies the HttpMethod of
the context’s Request It returns the context if it is Put else returns None Context -> Context option -
Step 16 Its time for Refactoring All Http Method filter
handlers looks for a particular HttpMethod let httpMethodFilter httpMethod ctx = match ctx.Request.HttpMethod = httpMethod with | true -> Some ctx | _ -> None let GET = httpMethodFilter Get -
Step 17 Define Path (Filter)Handler Path takes a string in
addition to a context. It verifies the string with the Path of the context’s Request It returns the context if it matches else returns None string -> Context -> Context option -
Let’s Play fsharpi —use:test.fsx fsi —use:test.fsx server "GET;/hello" (Path "/hello");;
server "GET;/hi" (Path "/hello");; server "GET;/hi" PUT;; server "GET;/hi" GET;; server "POST;/hi" PUT;; server "POST;/hi" POST;; -
Function Composition x f1 y y f2 z >> x
f1 >> f2 z x f1 y y f2 z >>x f1 >> f2 >> f3 z z f3 a -
f1 C C C f2 C C // Handler ->
Handler -> Context -> Context option // Handler -> Handler -> Handler let compose f1 f2 ctx = match f1 ctx with | Some ctx -> f2 ctx | None -> None Step 18 Function to compose functions -
Let’s Play fsharpi —use:test.fsx fsi —use:test.fsx server "GET;/hello" (GET >=>
Path "/hello" >=> OK "hello");; server "GET;/hello" (POST >=> Path "/hello" >=> OK "hello");; -
Step 20 Let’s Choose ! // Choose :: Handler list
-> Context -> Context option // Choose :: Handler list -> Handler let rec fib n = match n with | 1 -> 1 | 2 -> 1 | n -> fib(n-1) + fib(n-2) let rec firstEven nums = match nums with | [] -> None | x :: xs -> match x % 2 = 0 with | true -> Some x | _ -> firstEven xs -
The Real Play! fsharpi —use:play.fsx fsi —use:play.fsx let handlers =
Choose[ GET >=> Choose [ Path "/hello" >=> OK "hello" Path "/hi" >=> OK "hi" ] POST >=> Path "/hello" >=> OK "hello POST" ]