Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Fsharp

 Fsharp

A two hours presentation about fsharp given at itemis Stuttgart

747ee5b01d0969d624683652122fd377?s=128

Kolja Dummann

August 28, 2015
Tweet

Transcript

  1. F#

  2. What is it?

  3. It is a strongly typed, functional first language

  4. multiparadigm functional, imperative and object oriented

  5. originally developed by Microsoft Research

  6. now controlled by F# Foundation

  7. Apache 2 Licensed Runs on: CLR (Mono/.Net) Compiles to JavaScript

  8. originated from ML inspired by C#, OCAML, Haskell, …

  9. Language

  10. let x = 5 let y = 10 let z

    = x + y z = 10 Basic Syntax (Values)
  11. let addStr x y = (x + y).ToString() val addStr

    : x:int -> y:int -> string Basic Syntax (Arrow notation)
  12. Type inference Happens everywhere Parameters, Values, Generics

  13. let add (x : int) (y : int) = x

    + y Type inference
  14. let add (x : int) (y : int) = x

    + y let add x y = x + y Type inference
  15. let add (x : int) (y : int) = x

    + y let add x y = x + y add 5 10 Type inference
  16. let add (x : int) (y : int) = x

    + y let add x y = x + y add 5 10 add 3.14 4.56 Type inference
  17. let add (x : int) (y : int) = x

    + y let add x y = x + y add 5 10 add 3.14 4.56 add 3.14 10 Type inference
  18. let sign num = if num > 0 then "positive"

    elif num < 0 then "negative" else "zero" Type inference (more)
  19. let sign num = if num > 0 then "positive"

    elif num < 0 then "negative" else 0 Type inference (more)
  20. type IAnimal = interface… Type inference (more)

  21. type IAnimal = interface… type Dog = class interface IAnimal…

    Type inference (more)
  22. type IAnimal = interface… type Dog = class interface IAnimal…

    let getName (l : IAnimal) = … Type inference (more)
  23. type IAnimal = interface… type Dog = class interface IAnimal…

    let getName (l : IAnimal) = … let doStuffWithDog (d : Dog) = … Type inference (more)
  24. type IAnimal = interface… type Dog = class interface IAnimal…

    let getName (l : IAnimal) = … let doStuffWithDog (d : Dog) = … let takesStuff s = doStuffWithDog(s) getName(s) Type inference (more)
  25. Type inference (Generics)

  26. let giveMeAThree x = 3 'a -> int Type inference

    (Generics)
  27. let throwAwayFirstInput x y = y 'a -> 'b ->

    'b Type inference (Generics)
  28. Functional Programming

  29. Pattern Matching Describes control flow patterns match sequentially Checked for

    completness
  30. let getPrice name = match name with | "banana" ->

    0.79 | "watermelon" -> 3.49 | "tofu" -> 1.09 | _ -> nan Pattern Matching
  31. let getPrice = function | "banana" -> 0.79 | "watermelon"

    -> 3.49 | "tofu" -> 1.09 | _ -> nan Pattern Matching
  32. let sign = function | 0 -> 0 | x

    when x < 0 -> -1 | x when x > 0 -> 1 Pattern Matching
  33. Recursion Basic concept of FP Function calling itself

  34. let rec fact x = if x < 1 then

    1 else x * fact (x - 1) Recursion
  35. let rec count n = if n = 1000000 then

    printfn "done" else if n % 1000 = 0 then printfn "n: %i" n count (n + 1) Recursion (Tail)
  36. Higher order functions Function taking a function as argument and/or

    returning a function
  37. let passFive f = (f 5) val passFive : (int

    -> 'a) -> 'a Higher order functions
  38. let map it converter = converter it val map :

    'a -> ('a -> 'b) -> 'b Higher order functions
  39. let add x y = x + y let addFive

    = add 5 Higher order functions
  40. let add x y = x + y val add

    : int -> int -> int let addFive = add 5 val addFive : (int -> int) Higher order functions
  41. Option Types The “null” of functional programming Some or None

    Explicitly stat that some can be nothing
  42. > let div x y = x / y val

    div : int -> int -> int > div 10 5 val it : int = 2 > div 10 0 Option Types
  43. let sdiv x y = match y with | 0

    -> None | _ -> Some(x/y) val sdiv : int -> int -> int option Option Types
  44. > safediv 10 5 val it : int option =

    Some 2 > safediv 10 0 val it : int option = None Option Types
  45. let isFortyTwo = function | Some(42) -> true | Some(_)

    | None -> false > isFortyTwo (Some(43)) val it : bool = false > isFortyTwo (Some(42)) val it : bool = true Option Types
  46. Tuples a “Group” of values Often used for “multiple” return

    values
  47. > let average (a, b) = let sum = a

    + b sum / 2.0 val average : float * float -> float > average (10.0, 20.0) val it : float = 15.0 Tuples
  48. > let divrem x y = match y with |

    0 -> None | _ -> Some(x / y, x % y) val divrem : int -> int -> (int * int) option Tuples
  49. > divrem 100 20 val it : (int * int)

    option = Some (5, 0) > divrem 6 4 val it : (int * int) option = Some (1, 2) Tuples
  50. let greeting (name, language) = match (name, language) with |

    ("Steve", _) -> "Howdy, Steve" | (name, "Engl") -> "Hello, “ + name | (_, "French") -> "Bonjour!" | _ -> "DOES NOT COMPUTE" Tuples
  51. Records Tuples with names values

  52. type website = { Title : string; Url : string

    } Records
  53. type website = { Title : string; Url : string

    } > let homepage = { Title = "Google"; Url = "http://www.google.com" } val homepage : website Records
  54. > let homepage = { Title = "Wikibooks"; Url =

    "http://www.wikibooks.org/" } val homepage : website > homepage.Title val it : string = "Wikibooks" > homepage.Url val it : string = "http://www.wikibooks.org/" Records
  55. type TransactionItem = { Name : string; ID : int;

    ProcessedText : string; IsProcessed : bool } let processItem item = { item with ProcessedText = "Done"; IsProcessed = true } Records
  56. type coords = { X : float; Y : float

    } let getQuadrant = function | { X = 0.0; Y = 0.0 } -> "Origin" | item when item.X >= 0.0 && item.Y >= 0.0 -> "I" | item when item.X <= 0.0 && item.Y >= 0.0 ->"II" | item when item.X <= 0.0 && item.Y <= 0.0 ->"III" | item when item.X >= 0.0 && item.Y <= 0.0 -> "IV" Records
  57. Lists ordered collection of values immutable linked list

  58. > let numbers = [1; 2; 3; 4; 5; 6;

    7; 8; 9; 10] val numbers : int list [1; 2; 3; 4; "cat"; 6; 7] Lists
  59. > [1 .. 10] val it : int list =

    [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] > [1 .. 2 .. 10] val it : int list = [1; 3; 5; 7; 9] > ['a' .. 's'] val it : char list Lists
  60. let rec sum total = function | [] -> total

    | hd :: tl -> sum (hd + total) tl Lists
  61. Set / Map unordered collections immutable

  62. > Set.empty.Add(1).Add(2).Add(7) val it : Set<int> = set [1; 2;

    7] let a = Set.ofSeq [ 1 .. 10 ] let b = a a.Add(12) b.Add(13) Set / Map
  63. let capitals = [("Australia", "Canberra"); ("Canada", "Ottawa"); ("China", “Beijing”);] let

    canadaCapital = capitals.find("Canada") Set / Map
  64. Discriminated Unions tagged unions finite set of choices

  65. type switchstate = | On | Off let toggle =

    function | On -> Off | Off -> On let main() = let x = On let y = Off let z = toggle y Discriminated Unions
  66. type switchstate = | On | Off | Adjustable of

    float Discriminated Unions
  67. Imperative Programming (impure!1!!)

  68. Mutability Two types of mutability re alias & references to

    same memory
  69. > let mutable x = 5 val mutable x :

    int > x val it : int = 5 > x <- 10 val it : unit = () > x val it : int = 10 Mutability
  70. > let x = ref "hello";; val x : string

    ref > x;; (* returns ref instance *) val it : string ref = {contents = "hello";} > !x;; (* returns x.contents *) val it : string = "hello" > x := "world";; (* updates x.contents with a new value *) val it : unit = () > !x;; (* returns x.contents *) val it : string = "world" Mutability
  71. > let cell1 = ref 7;; val cell1 : int

    ref > let cell2 = cell1;; val cell2 : int ref > cell1 := 10;; val it : unit = () > !cell1;; val it : int = 10 > !cell2;; val it : int = 10 Mutability
  72. Typesafe (s)printf sprintf "Hi, I'm %s and I'm a %s"

    "Juliet" “Scorpio" sprintf "I'm %i years old" "kitty"
  73. Other Control flow: if/then, for, while Arrays: fixed size, mutable,

    fast mutable Collections/Maps Exceptions Operators: define & overload
  74. Object Orientated Programming

  75. OOP Classes/Interfaces Events: no magic modules/namespaces

  76. Cool Stuff

  77. Unit of Measurement additional dimension to typesystem statically checked

  78. Unit of Measurement [<Measure>] type m (* meter *) [<Measure>]

    type s (* second *)
  79. Unit of Measurement [<Measure>] type m (* meter *) [<Measure>]

    type s (* second *) [<Measure>] type kg (* kilogram *) [<Measure>] type N = (kg * m)/(s^2) (* Newtons *) [<Measure>] type Pa = N/(m^2) (* Pascals *)
  80. Unit of Measurement > let distance = 100.0<m> let time

    = 5.0<s> let speed = distance / time;; val distance : float<m> = 100.0 val time : float<s> = 5.0 val speed : float<m/s> = 20.0
  81. Unit of Measurement type triple<[<Measure>] 'a> = { a :

    float<'a>; b : float<'a>; c : float<‘a>} { a = 7.0<kg>; b = -10.5<_>; c = 0.5<_> } val it : triple<kg> = {a = 7.0; b = -10.5; c = 0.5;}
  82. Computation Expressions the easy monad

  83. Computation Expressions let read_line() = System.Console.ReadLine() let print_string(s) = printf

    "%s" s print_string "What's your name? " let name = read_line() print_string ("Hello, " + name)
  84. Computation Expressions let read_line(f) = f(System.Console.ReadLine()) let print_string(s, f) =

    f(printf "%s" s) print_string("What's your name? ", fun () -> read_line(fun name -> print_string("Hello, " + name, fun () -> () ) ) )
  85. Computation Expressions let getNum msg = printf "%s" msg match

    System.Int32.TryParse(System.Console.ReadLine()) with | (true, n) when n >= 0 && n <= 100 -> Some(n) | _ -> None match getNum "#1: " with | Some(x) -> match getNum "#2: " with | Some(y) -> match getNum "#3: " with | Some(z) -> Some(x + y + z) | None -> None | None -> None | None -> None
  86. Computation Expressions let bind(input, rest) = match System.Int32.TryParse(input()) with |

    (true, n) when n >= 0 && n <= 100 -> rest(n) | _ -> None let createMsg msg = fun () -> printf "%s" msg; System.Console.ReadLine() bind(createMsg "#1: ", fun x -> bind(createMsg "#2: ", fun y -> bind(createMsg "#3: ", fun z -> Some(x + y + z) ) ) )
  87. Computation Expressions let bind(input, rest) = rest(input()) let download (url

    : string) = bind( (fun () -> new System.Net.WebClient()), fun webclient -> bind( (fun () -> webclient.DownloadString(url)), fun html -> bind( (fun () -> Regex.Matches(html, @"http://\S+") ), fun matches -> printMsg ("Found " + matches.Count.ToString() + " links") ) ) ) ["http://www.google.com/"; "http://microsoft.com/"; "http://www.wordpress.com/"; "http://www.peta.org"] |> Seq.iter download
  88. Computation Expressions let bind(input, rest) = ThreadPool.QueueUserWorkItem(new WaitCallback(fun _ ->

    rest(input()))) let download (url : string) = bind( (fun () -> new System.Net.WebClient()), fun webclient -> bind( (fun () -> webclient.DownloadString(url)), fun html -> bind( (fun () -> Regex.Matches(html, @"http://\S+") ), fun matches -> printMsg ("Found " + matches.Count.ToString() + " links") ) ) ) ["http://www.google.com/"; "http://microsoft.com/"; "http://www.wordpress.com/"; "http://www.peta.org"] |> Seq.iter download
  89. Computation Expressions let bind(input, rest) = match System.Int32.TryParse(input()) with |

    (true, n) when n >= 0 && n <= 100 -> rest(n) | _ -> None let createMsg msg = fun () -> printf "%s" msg; System.Console.ReadLine() bind(createMsg "#1: ", fun x -> bind(createMsg "#2: ", fun y -> bind(createMsg "#3: ", fun z -> Some(x + y + z) ) ) )
  90. Computation Expressions > type MaybeBuilder() = member this.Bind(x, f) =

    printfn "this.Bind: %A" x match x with | Some(x) when x >= 0 && x <= 100 -> f(x) | _ -> None member this.Delay(f) = f() member this.Return(x) = Some x
  91. Computation Expressions let maybe = new MaybeBuilder() let sugared =

    maybe { let x = 12 let! y = Some 11 let! z = Some 30 return x + y + z }
  92. Computation Expressions let maybe = new MaybeBuilder() let desugared =

    maybe.Delay(fun () -> let x = 12 maybe.Bind(Some 11, fun y -> maybe.Bind(Some 30, fun z -> maybe.Return(x + y + z) ) ) )
  93. Async Workflows Based on Computation Expressions Used to run code

    in parallel
  94. Async Workflows let extractLinks url = async { let webClient

    = new System.Net.WebClient() printfn "Downloading %s" url let html = webClient.DownloadString(url : string) printfn "Got %i bytes" html.Length let matches = Regex.Matches(html, @"http://\S+") printfn "Got %i links" matches.Count return url, matches.Count };;
  95. Mailboxes Erlang style message passing reply channels Async Input queue

  96. Mailboxes type msg = | Incr of int | Fetch

    of AsyncReplyChannel<int> let counter = MailboxProcessor.Start(fun inbox -> let rec loop n = async { let! msg = inbox.Receive() match msg with | Incr(x) -> return! loop(n + x) | Fetch(replyChannel) -> replyChannel.Reply(n) return! loop(n) } loop 0)
  97. Mailboxes > counter.Post(Incr 7);; val it : unit = ()

    > counter.Post(Incr 50);; val it : unit = () > counter.PostAndReply(fun replyChannel -> Fetch replyChannel);; val it : int = 57
  98. TypeProviders Compile time generated types Based on arbitrary information

  99. TypeProviders

  100. TypeProviders

  101. Interested? Go to: fshrap.org fsharpforfunandprofit.com en.wikibooks.org/wiki/F_Sharp_Programming

  102. Thanks!