KEMBAR78
Functional Programming in F# | PDF
Dmitri Nesteruk
dmitrinesteruk @ gmail.com
http://spbalt.net
“…a programming paradigm that
treats computation as the evaluation
of mathematical functions and
avoids state and mutable data”
                                       —Wikipedia
  Higher-order functions
   
   i => j => f(j)

   Pure functions
   
   Immutability
   
   No side effects

   (Tail) recursion
   
   let f(x) = …; f(x-1);

   Pattern matching
  Math
   
   Probabilistic models

   Symbolic processing (parsing/lexing)
   
   Symbolic differentiation
   
   Circuit verification
  Multi-paradigm language in .NET stack
   
   Functional
   
   Imperative

   Performance similar to C#

   Interactive console

   Support in Visual Studio
   
   Debugger
   
   Editor

   Mono support
  #light 
    printfn “Hello, F#!” 


   #light 
    Light syntax – cuts down on ceremony when
    writing code
  
       Indentation instead of begin/end
  
       Use of in,done keywords not required
  
       No semicolons
  
       Currently mandatory – will be default in future
  printfn “Hello, F#”
    Writes a line to the console
   
   A top-level binding (like a global function)
   
   Part of FSharp.Core
     
   Referenced implicitly
   
   Appears in a generated _main() 
   
   Can “Go To Definition”
  Can do it with a function

  let sayHello = 
    printfn “Hello, F#!” 
  sayHello 


   Or pass a parameter

  let sayHello s = 
    printfn s 
  sayHello "Hello, F#!" 
  Application operator |> (forward pipe)

  let sayHello s = 
    s |> printfn // same as printfn s 


   Explicit types

  let length a = a.Length; // not ok 
  let length (a:string) = 
    a.Length // ok
  Recursive definition

  let rec factorial n = 
    if n <= 1 then 1  
    else n * factorial(n‐1) 


   Mutual recursion 

  let rec funcA x = 1 + funcB(x) 
  and funcB x = 1 – funcA(x) 
  One statement per line, use in for more
   
   let powerOf4 x = 
         let y = x * x in y * y 

   No implicit conversions
   
   let GetXName xname = 
         XName.op_Implicit(xname) 

   Aggressive strong typing
   
   let o:obj = “test”; // fails 
   
   let o = box “test”; // ok 

   Mutability must be explicit
   
   mutable keyword
   
   variable <‐ value to assign
  Clever switch statement

   Can match values of any type


   let matchMe x = 
      match x with 
      | 1 ‐> printfn "one"  
      | 2 ‐> printfn "two"  
      | _ ‐> printfn "something else"


   Cannot bind same pattern element twice
   
   Cannot match (x, x)
   
   Can match (x, y) when x = y
  Tuple

     Option value

     Array

     Sequence

     List
  Contains several values of any types

   No more Pair<T,U> etc. classes


   let sumAndProduct a b = 
      (a+b, a*b)


   let (s, p) = sumAndProduct 2 3 
    printfn "%d %d" s p 


   Tuples use comma ,
    Other structures use semicolon ;
  null is typically not used with F# types

   Presence or absence can be discriminated with
    an option value, which is
   
   None 
   
   Some of 'a 

   Use pattern matching 

  match x with 
  | Some(name) ‐> printfn name 
  | None ‐> printfn “anonymous” 
  Your typical CLR array

  let people = [|  
    “john”;  
    “jane”;  
    “jack”  
  |] 


   people.Length 
   
   yields 3
  Enumerable values
    
   let a = seq [1; 2; 3] 
    
   let b = seq { for i in 1 .. 10 ‐> (i*i) } 

   Lazy-inited
    
   seq { 1 .. 10000000 } 

   Step
    
   seq { 1 .. 2 .. 10 } 
    
   yields 1, 3, 5, 7, 9

   Strings are char sequences
    
   printfn "%d" (Seq.length "Hello") 

   Iterated with for .. in .. do
    
   for i in mySeq do printfn “%d” i 
  Linked list of values

  [1; 2; 3]


   Has head and tail
   
       Head is the first element 
   
       Tail is everything else 
   
       [] is the empty list
   
       [1, 2, 3] has length of 1:)
  let a = [1; 2; 3] 

     Head = 1 

     Tail = [2; 3] 

     let b = 0 :: a 
     
   [0; 1; 2; 3] 

   let c = a @ b 
     
   [1; 2; 3; 0; 1; 2; 3] 
  let rec sumAll myList = 
      match myList with 
      | h :: t ‐> head + sumAll(t) 
      | [] ‐> 0


   let rec nonZero myList = 
      match myList with 
      | 0 :: t ‐> 1 :: nonZero t 
      | h :: t ‐> h :: nonZero t 
      | [] ‐> [] 


   let rec htmlDecode text = 
      match text with 
      | ‘&’ :: ‘g’ :: ‘t’ :: ‘;’ :: tail ‐> 
          ‘>’ :: htmlDecode tail // and so on   
  A non-exhaustive match will throw a
    MatchFailureException 


   Patterns can be grouped
   
   match person with 
       | a :: (b :: c as subGroup) ‐> 
         match subGroup with 
  Anonymous functions

     Functional composition

     Partial application

     Memoization
  A way of defining nameless functions
   
   fun x ‐> x * 2 

   Can be passed as parameter

   Can be bound, i.e.
   
   let square = fun x ‐> x * x 
  Used to provide LINQ-like features to lists and sequences

   let myList = [1; 2; 3]

   List.iter (fun f ‐> printfn “%d” f) myList 
    
   Iterates through the collection

   List.map (fun f ‐> f + 1) myList 
    
   Returns a modified list [2; 3; 4] – LINQ Select()

   List.filter (fun f ‐> f % 2 = 0) myList 
    
   Returns only odd elements – LINQ Where()

   Other useful functions (e.g., List.to_array)

   Similar features in seq 
  Operators can be piped
   
   values |> List.map (fun f ‐> f + 1) 
              |> List.filter(fun f ‐> f > 0) 


   And functionally composed
   
   let even = List.filter  
                       (fun f ‐> f % 2 = 0) 
       let positive = List.filter 
                       (fun f ‐> f > 0) 
       let evenAndPos = even >> positive 
   
   evenAndPos [1; ‐2; 4] 
     
   yields [4]
  let squareThis x = 
      x * x  

   let addFive x = 
      x + 5 

   5 |> squareThis |> addFive 
  
   yields 30

   let squareAndAddFive = 
      squareThis >> addFive 

   squareThisAndAddFive 5 
  
   yields 30
  let shift (dx, dy) (px, py) =  
      (px + dx, py + dy) 


   shift (1, 0) (100, 100) 
  
   result is (101, 100)


   let shiftRight = shift (1, 0)


   shiftRight (100, 100) 
  
   result is (101, 100)
  Keep a lookaside table of computed values


   let rec fib n = 
      if n <= 2 then 1 
      else fib(n‐1) + fib(n‐2) 


   Computed values wasted
   
   Why not cache them?
  let fibFast n = 
      let t = new Dictionary<int,int>() 
      let rec fibCached n = 
        if t.ContainsKey(n) then t.[n] 
        else if n <= 2 then 1 
        else let res =  
          fibCached(n‐1) + fibCached(n‐2) 
          t.Add(n,res) 
          res 
      fibCached n 
  Computation expressions = workflows
   
   builder { expression }

   Usage
   
   General programming (e.g., seq { … })
   
   Asynchronous workflows
   
   Database queries
  Define a builder type

   Computation expression constructs map onto
    the builder methods (are de-sugared)
   
   E.g., let a = b in c  maps onto
   
   builder.Let(b, (fun a ‐> c)) 

   Builder affects behavior of contained
    expressions
   
   E.g., makes them asynchronous
  Many .NET APIs feature Begin/End pairs
   
   E.g., BeginGetResponse/EndGetResponse

   Frameworks make code look sequential
   
   Abstracting away Begin/End calls
   
   C#  AsyncEnumerator from PowerThreading
   
   F#  Async workflows

   Goals
   
   Begin an asynchronous operation
   
   Resume execution when it’s done
   
   Let threads interleave
  Async<'a> 
   
   Represents a result of 'a computed in the future

   This class needs to know about begin/end
    pairs
   
   Extends existing types with XXXAsync() calls
   
   type WebRequest with 
         member x.GetResponseAsync() =  
           Async.BuildPrimitive( 
             x.BeginGetResponse, 
             x.EndGetResponse) 
  Once Async knows about Begin/End elements
    we can use the async { … } workflow
  
   let download url = 
        async { 
          let rq = WebRequest.Create(url)    
          let! resp = rq.GetResponseAsync() 
          use s = resp.GetResponseStram() 
          use r = new StreamReader(s) 
          r.ReadToEnd() 
        } 
  
   let! fires off BeginGetResponse() asynchronously
  
   and waits on completion
  let urls = [ 
      “http://spbalt.net”; 
      “http://sp.ineta.ru”; 
      “http://altdotnet.org” ]


   Spawn one-by-one
   
   for url in urls do 
         Async.Spawn(download(url))


   Send all at once
   
   urls |> List.map(fun f ‐> download(f)) 
            |> Async.Parallel |> Async.Run 
  Foundations of F#
    Robert Pickering


   Expert F#
    Don Syme et al.


   F# for Scientists
    Jon Harrop
Functional Programming in F#

Functional Programming in F#

  • 1.
    Dmitri Nesteruk dmitrinesteruk @gmail.com http://spbalt.net
  • 2.
    “…a programming paradigmthat treats computation as the evaluation of mathematical functions and avoids state and mutable data” —Wikipedia
  • 3.
      Higher-order functions   i => j => f(j)   Pure functions   Immutability   No side effects   (Tail) recursion   let f(x) = …; f(x-1);   Pattern matching
  • 4.
      Math   Probabilistic models   Symbolic processing (parsing/lexing)   Symbolic differentiation   Circuit verification
  • 5.
      Multi-paradigm languagein .NET stack   Functional   Imperative   Performance similar to C#   Interactive console   Support in Visual Studio   Debugger   Editor   Mono support
  • 6.
      #light  printfn “Hello, F#!”    #light  Light syntax – cuts down on ceremony when writing code   Indentation instead of begin/end   Use of in,done keywords not required   No semicolons   Currently mandatory – will be default in future
  • 7.
      printfn “Hello, F#” Writes a line to the console   A top-level binding (like a global function)   Part of FSharp.Core   Referenced implicitly   Appears in a generated _main()    Can “Go To Definition”
  • 8.
      Can doit with a function let sayHello =    printfn “Hello, F#!”  sayHello    Or pass a parameter let sayHello s =    printfn s  sayHello "Hello, F#!" 
  • 9.
      Application operator|> (forward pipe) let sayHello s =    s |> printfn // same as printfn s    Explicit types let length a = a.Length; // not ok  let length (a:string) =    a.Length // ok
  • 10.
      Recursive definition let rec factorial n =    if n <= 1 then 1     else n * factorial(n‐1)    Mutual recursion  let rec funcA x = 1 + funcB(x)  and funcB x = 1 – funcA(x) 
  • 11.
      One statementper line, use in for more   let powerOf4 x =    let y = x * x in y * y    No implicit conversions   let GetXName xname =    XName.op_Implicit(xname)    Aggressive strong typing   let o:obj = “test”; // fails    let o = box “test”; // ok    Mutability must be explicit   mutable keyword   variable <‐ value to assign
  • 12.
      Clever switchstatement   Can match values of any type   let matchMe x =    match x with    | 1 ‐> printfn "one"     | 2 ‐> printfn "two"     | _ ‐> printfn "something else"   Cannot bind same pattern element twice   Cannot match (x, x)   Can match (x, y) when x = y
  • 13.
      Tuple   Option value   Array   Sequence   List
  • 14.
      Contains severalvalues of any types   No more Pair<T,U> etc. classes   let sumAndProduct a b =    (a+b, a*b)   let (s, p) = sumAndProduct 2 3  printfn "%d %d" s p    Tuples use comma , Other structures use semicolon ;
  • 15.
      null istypically not used with F# types   Presence or absence can be discriminated with an option value, which is   None    Some of 'a    Use pattern matching  match x with  | Some(name) ‐> printfn name  | None ‐> printfn “anonymous” 
  • 16.
      Your typicalCLR array let people = [|     “john”;     “jane”;     “jack”   |]    people.Length    yields 3
  • 17.
      Enumerable values   let a = seq [1; 2; 3]    let b = seq { for i in 1 .. 10 ‐> (i*i) }    Lazy-inited   seq { 1 .. 10000000 }    Step   seq { 1 .. 2 .. 10 }    yields 1, 3, 5, 7, 9   Strings are char sequences   printfn "%d" (Seq.length "Hello")    Iterated with for .. in .. do   for i in mySeq do printfn “%d” i 
  • 18.
      Linked listof values [1; 2; 3]   Has head and tail   Head is the first element    Tail is everything else    [] is the empty list   [1, 2, 3] has length of 1:)
  • 19.
      let a = [1; 2; 3]    Head = 1    Tail = [2; 3]    let b = 0 :: a    [0; 1; 2; 3]    let c = a @ b    [1; 2; 3; 0; 1; 2; 3] 
  • 20.
      let rec sumAll myList =    match myList with    | h :: t ‐> head + sumAll(t)    | [] ‐> 0   let rec nonZero myList =    match myList with    | 0 :: t ‐> 1 :: nonZero t    | h :: t ‐> h :: nonZero t    | [] ‐> []    let rec htmlDecode text =    match text with    | ‘&’ :: ‘g’ :: ‘t’ :: ‘;’ :: tail ‐>        ‘>’ :: htmlDecode tail // and so on   
  • 21.
      A non-exhaustivematch will throw a MatchFailureException    Patterns can be grouped   match person with  | a :: (b :: c as subGroup) ‐>    match subGroup with 
  • 22.
      Anonymous functions   Functional composition   Partial application   Memoization
  • 23.
      A wayof defining nameless functions   fun x ‐> x * 2    Can be passed as parameter   Can be bound, i.e.   let square = fun x ‐> x * x 
  • 24.
      Used toprovide LINQ-like features to lists and sequences   let myList = [1; 2; 3]   List.iter (fun f ‐> printfn “%d” f) myList    Iterates through the collection   List.map (fun f ‐> f + 1) myList    Returns a modified list [2; 3; 4] – LINQ Select()   List.filter (fun f ‐> f % 2 = 0) myList    Returns only odd elements – LINQ Where()   Other useful functions (e.g., List.to_array)   Similar features in seq 
  • 25.
      Operators canbe piped   values |> List.map (fun f ‐> f + 1)         |> List.filter(fun f ‐> f > 0)    And functionally composed   let even = List.filter                   (fun f ‐> f % 2 = 0)  let positive = List.filter                  (fun f ‐> f > 0)  let evenAndPos = even >> positive    evenAndPos [1; ‐2; 4]    yields [4]
  • 26.
      let squareThis x =    x * x     let addFive x =    x + 5    5 |> squareThis |> addFive    yields 30   let squareAndAddFive =    squareThis >> addFive    squareThisAndAddFive 5    yields 30
  • 27.
      let shift (dx, dy) (px, py) =     (px + dx, py + dy)    shift (1, 0) (100, 100)    result is (101, 100)   let shiftRight = shift (1, 0)   shiftRight (100, 100)    result is (101, 100)
  • 28.
      Keep alookaside table of computed values   let rec fib n =    if n <= 2 then 1    else fib(n‐1) + fib(n‐2)    Computed values wasted   Why not cache them?
  • 29.
      let fibFast n =    let t = new Dictionary<int,int>()    let rec fibCached n =      if t.ContainsKey(n) then t.[n]      else if n <= 2 then 1      else let res =         fibCached(n‐1) + fibCached(n‐2)        t.Add(n,res)        res    fibCached n 
  • 30.
      Computation expressions= workflows   builder { expression }   Usage   General programming (e.g., seq { … })   Asynchronous workflows   Database queries
  • 31.
      Define abuilder type   Computation expression constructs map onto the builder methods (are de-sugared)   E.g., let a = b in c  maps onto   builder.Let(b, (fun a ‐> c))    Builder affects behavior of contained expressions   E.g., makes them asynchronous
  • 32.
      Many .NETAPIs feature Begin/End pairs   E.g., BeginGetResponse/EndGetResponse   Frameworks make code look sequential   Abstracting away Begin/End calls   C#  AsyncEnumerator from PowerThreading   F#  Async workflows   Goals   Begin an asynchronous operation   Resume execution when it’s done   Let threads interleave
  • 33.
      Async<'a>    Represents a result of 'a computed in the future   This class needs to know about begin/end pairs   Extends existing types with XXXAsync() calls   type WebRequest with    member x.GetResponseAsync() =       Async.BuildPrimitive(        x.BeginGetResponse,        x.EndGetResponse) 
  • 34.
      Once Asyncknows about Begin/End elements we can use the async { … } workflow   let download url =    async {      let rq = WebRequest.Create(url)         let! resp = rq.GetResponseAsync()      use s = resp.GetResponseStram()      use r = new StreamReader(s)      r.ReadToEnd()    }    let! fires off BeginGetResponse() asynchronously   and waits on completion
  • 35.
      let urls = [    “http://spbalt.net”;    “http://sp.ineta.ru”;    “http://altdotnet.org” ]   Spawn one-by-one   for url in urls do    Async.Spawn(download(url))   Send all at once   urls |> List.map(fun f ‐> download(f))       |> Async.Parallel |> Async.Run 
  • 36.
      Foundations ofF# Robert Pickering   Expert F# Don Syme et al.   F# for Scientists Jon Harrop