Welcome
F# |> Introduction
All characters appearing in this work are fictitious.
Any resemblance to real persons, living or dead, is purely coincidental.
F# is awesome
F# syntax example
let add x y = x + y
let x = 5
let username = "rowan.williams"
let pages = [10; 20; 50; 100]
x = x + 1 //false (and does not make sense)
F# vs. C#
C#:
namespace Math
{
public static class Helpers
{
public static int Add(int x, int y)
{
return x + y;
}
}
}
F#:
let add x y = x + y
F# syntax: functions
let add x y = x + y
let square x = x * x
let squareSum x y =
let sum = add x y
square sum
let squareRes func x y =
let result = func x y
square result
add 2 3 //5
square 5 //25
squareSum 2 3 //25
squareRes add 2 3 //25
squareRes (*) 2 3 //36
let changePrice p =
let price = if p < 0 then 0 else p
price * 0.1
F# type inference
// add : int -> int -> int
let add x y = x + y
Func<int, int, int>
// add5 : int -> int
let add5 = add 5
let add7 = (+) 7
add5 10 // returns 15
add7 10 // returns 17
F# syntax: partial application
//find: string -> string -> obj
let find parent elem = …
//findInBody: string -> obj
let findInBody = find "body"
//findInView: string -> obj
let findInView = find "#main-view"
find "body" "#btn"
findInBody "#btn"
findInView "#save"
//writeTo: string -> string -> unit
let writeTo elem text = …
let setUsername = writeTo "#username"
let setPassword = writeTo "#password"
let setSearch = writeTo "#global-search"
writeTo "#username" "sb"
setUsername "mh.incite"
setPassword "Password1"
setSearch "test"
F# syntax: unit
//like ‘void’ but is a real value!
let useless () = true //useless: unit -> bool
() unit
let useless2() = () //useless2: unit -> unit
let doSomething text =
printfn "doing %s" text
()
//doSomething: string -> unit
let doSomething text =
printfn "doing %s" text
let doSomething = printfn "doing %s"
//or we can do this
//or just this
F# syntax: Tuples
let internal = (63, "internal")
let external = 64, "external"
//internal: int * string
let lang = "F#", "functional", 5 //lang: string * string * int
let (typeId, typeName) = internal
let name, kind, years = lang
// typeId: int = 63
// typeName: string = "internal"
// name: string = "F#"
// kind: string = "functional"
// years: int = 5
internal = external
external > internal
// false
// true
F# syntax: Lists
let newList = 101 :: ints
// [1; 2; 3] = 1 :: 2 :: 3 :: []
// [101; 1; 2; 3; 4; 5]
let x :: xs = ints
let evens xs =
let isEven x = x%2 = 0
List.filter isEven xs
// x: int = 1
// xs: int list = [2; 3; 4; 5]
// evens: int list -> int list
let empty = []
let ints = [1..5]
let names = [(1,"Rong"); (2,"Jose")]
let chars = [‘a’..’g’]
let odds = [1..2..10]
// empty: ‘a list
// [1; 2; 3; 4; 5]
// [(1, "Rong"); (2, "Jose")]
// [‘a’; ‘b’; ‘c’...]
// [1; 3; 5; 7; 9]
F# syntax: List Comprehension (generators)
let squares = [for i in odds -> x * x] // [1; 9; 25;]
[for x in odds do
for y in evens do
yield x * y]
// [2; 4; 6; 12; 10; 20]
let odds = [1..2..5]
let evens = [2..2..5]
let chars = [‘a’; ‘b’]
// [1; 3; 5;]
// [2; 4]
// [‘a’; ‘b’]
[for i in evens do
for c in chars -> (i, c)]
[
(2, 'a')
(2, 'b')
(4, 'a')
(4, 'b')
]
[for x in 1..5 do if x%2=0 then yield x] // [2; 4]
TAB FOUR TAB FIVE
F# goodness: Pipeline
let sumOfSquares n =
List.sum (List.map square [1..n])
let sumOfSquares n =
[1..n] |> List.map square |> List.sum
let sumOfSquaresOfEvens n =
let isEven x = x%2 = 0
[1..n]
|> List.filter isEven
|> List.map square
|> List.sum
TAB FIVE
F# goodness: Pipeline
let result =
httpGet url
|> getContent
|> stripHtml
|> spellcheck
let url = "http://someServer/api/data"
let response = httpGet url
let content = getContent response
let plainText = stripHtml content
let result = spellcheck plainText
let response = httpGet url
let result = spellcheck (stripHtml (getContent response))
TAB TWO TAB FIVE
F# syntax: Records
type Person = {FirstName: string; LastName: string; Age: int}
type Address = {Street: string; City: string}
let rowan = {FirstName="Rowan"; LastName="Williams"; Age=37}
let olderRowan = {rowan with Age=38}
olderRowan = rowan //false
olderRowan > rowan //true
TAB TWO
TAB FOUR TAB FIVE
F# syntax: Discriminated Unions
type Response =
| Success of int * string
| Failure of string
type Command =
| CreateUser of Person * Role
| UpdateUser of int * Person
| SetRole of int * Role
| DeleteUser of int
//many, many lines of C# code
let makeRowan = CreateUser(rowan, Visitor)
let ageRowan = UpdateUser(1, olderRowan)
type Role = Admin | Member | Visitor
TAB FIVE
F# syntax: Discriminated Unions
type WorkingUnit =
| Worker of Person
| Team of WorkingUnit list
let jsGuy = Worker {First="Troy"; Last="Wilson"}
let buildGuy = Worker {First="Murtuz"; Last="Chalabov"}
let teamAwesome = Team [jsGuy; buildGuy]
//many, many lines of C# code
F# syntax: Pattern Matching
let manageWorkers workforce =
match workforce with
| Worker {FirstName="Jimmy"} -> printfn "Superman!"
| Worker man -> printfn "Just a man: %s" man.FirstName
| Team people -> printfn "%i people" (List.length people)
let checkList lst =
match lst with
| [] -> printfn "List is empty"
| [elem] -> printfn "Just one element %O" elem
| 1 :: xs -> printfn "Starts with 1"
| _ :: x :: xs -> printfn "Secons element is %O" x
| _ -> () //do nothing
F# syntax: Pattern Matching
type Role = SystemAdmin | CompanyAdmin | Member
let loginAs userRole =
//usefulness of internal functions
let login uname pwd =
setUsername uname
setPassword pwd
click "#btnLogin"
match userRole with
| SystemAdmin -> login "mh.incite" "Password1"
| CompanyAdmin -> login "trudi.wilson" "Password1"
| Member -> login "ivan.chen" "Password1"
F# syntax: Option type
//Already defined in F#
type Option<‘a> =
| Some of ‘a
| None
goodResp: string option
badResp: string option
let goodResp = Some "Hello F#"
let badResp = None
let printResponse response =
match response with
| Some data -> printfn "%O" data
| None -> printfn "Got nothing :("
let clickSave() =
let elem = findElement "#btnSave"
match elem with
| Some btn -> click btn
| None -> ()
clickSave: unit -> unit
printResp: 'a option -> unit
Now when you know F#
let success =
F# |> Canopy |> Selenium
What is Canopy
• Easy to use (written in F#)
• Works on top of Selenium
• Works with many browsers (IE, Chrome, Firefox, Safari, Android)
• Developers-friendly
OK, now…
Show me the code!

F# intro

  • 1.
    Welcome F# |> Introduction Allcharacters appearing in this work are fictitious. Any resemblance to real persons, living or dead, is purely coincidental.
  • 2.
  • 3.
    F# syntax example letadd x y = x + y let x = 5 let username = "rowan.williams" let pages = [10; 20; 50; 100] x = x + 1 //false (and does not make sense)
  • 4.
    F# vs. C# C#: namespaceMath { public static class Helpers { public static int Add(int x, int y) { return x + y; } } } F#: let add x y = x + y
  • 5.
    F# syntax: functions letadd x y = x + y let square x = x * x let squareSum x y = let sum = add x y square sum let squareRes func x y = let result = func x y square result add 2 3 //5 square 5 //25 squareSum 2 3 //25 squareRes add 2 3 //25 squareRes (*) 2 3 //36 let changePrice p = let price = if p < 0 then 0 else p price * 0.1
  • 6.
    F# type inference //add : int -> int -> int let add x y = x + y Func<int, int, int> // add5 : int -> int let add5 = add 5 let add7 = (+) 7 add5 10 // returns 15 add7 10 // returns 17
  • 7.
    F# syntax: partialapplication //find: string -> string -> obj let find parent elem = … //findInBody: string -> obj let findInBody = find "body" //findInView: string -> obj let findInView = find "#main-view" find "body" "#btn" findInBody "#btn" findInView "#save" //writeTo: string -> string -> unit let writeTo elem text = … let setUsername = writeTo "#username" let setPassword = writeTo "#password" let setSearch = writeTo "#global-search" writeTo "#username" "sb" setUsername "mh.incite" setPassword "Password1" setSearch "test"
  • 8.
    F# syntax: unit //like‘void’ but is a real value! let useless () = true //useless: unit -> bool () unit let useless2() = () //useless2: unit -> unit let doSomething text = printfn "doing %s" text () //doSomething: string -> unit let doSomething text = printfn "doing %s" text let doSomething = printfn "doing %s" //or we can do this //or just this
  • 9.
    F# syntax: Tuples letinternal = (63, "internal") let external = 64, "external" //internal: int * string let lang = "F#", "functional", 5 //lang: string * string * int let (typeId, typeName) = internal let name, kind, years = lang // typeId: int = 63 // typeName: string = "internal" // name: string = "F#" // kind: string = "functional" // years: int = 5 internal = external external > internal // false // true
  • 10.
    F# syntax: Lists letnewList = 101 :: ints // [1; 2; 3] = 1 :: 2 :: 3 :: [] // [101; 1; 2; 3; 4; 5] let x :: xs = ints let evens xs = let isEven x = x%2 = 0 List.filter isEven xs // x: int = 1 // xs: int list = [2; 3; 4; 5] // evens: int list -> int list let empty = [] let ints = [1..5] let names = [(1,"Rong"); (2,"Jose")] let chars = [‘a’..’g’] let odds = [1..2..10] // empty: ‘a list // [1; 2; 3; 4; 5] // [(1, "Rong"); (2, "Jose")] // [‘a’; ‘b’; ‘c’...] // [1; 3; 5; 7; 9]
  • 11.
    F# syntax: ListComprehension (generators) let squares = [for i in odds -> x * x] // [1; 9; 25;] [for x in odds do for y in evens do yield x * y] // [2; 4; 6; 12; 10; 20] let odds = [1..2..5] let evens = [2..2..5] let chars = [‘a’; ‘b’] // [1; 3; 5;] // [2; 4] // [‘a’; ‘b’] [for i in evens do for c in chars -> (i, c)] [ (2, 'a') (2, 'b') (4, 'a') (4, 'b') ] [for x in 1..5 do if x%2=0 then yield x] // [2; 4]
  • 12.
    TAB FOUR TABFIVE F# goodness: Pipeline let sumOfSquares n = List.sum (List.map square [1..n]) let sumOfSquares n = [1..n] |> List.map square |> List.sum let sumOfSquaresOfEvens n = let isEven x = x%2 = 0 [1..n] |> List.filter isEven |> List.map square |> List.sum
  • 13.
    TAB FIVE F# goodness:Pipeline let result = httpGet url |> getContent |> stripHtml |> spellcheck let url = "http://someServer/api/data" let response = httpGet url let content = getContent response let plainText = stripHtml content let result = spellcheck plainText let response = httpGet url let result = spellcheck (stripHtml (getContent response))
  • 14.
    TAB TWO TABFIVE F# syntax: Records type Person = {FirstName: string; LastName: string; Age: int} type Address = {Street: string; City: string} let rowan = {FirstName="Rowan"; LastName="Williams"; Age=37} let olderRowan = {rowan with Age=38} olderRowan = rowan //false olderRowan > rowan //true
  • 15.
    TAB TWO TAB FOURTAB FIVE F# syntax: Discriminated Unions type Response = | Success of int * string | Failure of string type Command = | CreateUser of Person * Role | UpdateUser of int * Person | SetRole of int * Role | DeleteUser of int //many, many lines of C# code let makeRowan = CreateUser(rowan, Visitor) let ageRowan = UpdateUser(1, olderRowan) type Role = Admin | Member | Visitor
  • 16.
    TAB FIVE F# syntax:Discriminated Unions type WorkingUnit = | Worker of Person | Team of WorkingUnit list let jsGuy = Worker {First="Troy"; Last="Wilson"} let buildGuy = Worker {First="Murtuz"; Last="Chalabov"} let teamAwesome = Team [jsGuy; buildGuy] //many, many lines of C# code
  • 17.
    F# syntax: PatternMatching let manageWorkers workforce = match workforce with | Worker {FirstName="Jimmy"} -> printfn "Superman!" | Worker man -> printfn "Just a man: %s" man.FirstName | Team people -> printfn "%i people" (List.length people) let checkList lst = match lst with | [] -> printfn "List is empty" | [elem] -> printfn "Just one element %O" elem | 1 :: xs -> printfn "Starts with 1" | _ :: x :: xs -> printfn "Secons element is %O" x | _ -> () //do nothing
  • 18.
    F# syntax: PatternMatching type Role = SystemAdmin | CompanyAdmin | Member let loginAs userRole = //usefulness of internal functions let login uname pwd = setUsername uname setPassword pwd click "#btnLogin" match userRole with | SystemAdmin -> login "mh.incite" "Password1" | CompanyAdmin -> login "trudi.wilson" "Password1" | Member -> login "ivan.chen" "Password1"
  • 19.
    F# syntax: Optiontype //Already defined in F# type Option<‘a> = | Some of ‘a | None goodResp: string option badResp: string option let goodResp = Some "Hello F#" let badResp = None let printResponse response = match response with | Some data -> printfn "%O" data | None -> printfn "Got nothing :(" let clickSave() = let elem = findElement "#btnSave" match elem with | Some btn -> click btn | None -> () clickSave: unit -> unit printResp: 'a option -> unit
  • 20.
    Now when youknow F# let success = F# |> Canopy |> Selenium
  • 21.
    What is Canopy •Easy to use (written in F#) • Works on top of Selenium • Works with many browsers (IE, Chrome, Firefox, Safari, Android) • Developers-friendly
  • 22.