functional programming in f#

37
Dmitri Nesteruk dmitrinesteruk @ gmail.com http://spbalt.net

Upload: dmitri-nesteruk

Post on 18-Dec-2014

1.518 views

Category:

Technology


2 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Functional Programming in F#

Dmitri Nesteruk dmitrinesteruk @ gmail.com http://spbalt.net

Page 2: Functional Programming in F#

“…a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data”

—Wikipedia

Page 3: Functional Programming in F#

 Higher-order functions   i => j => f(j)

  Pure functions   Immutability   No side effects

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

  Pattern matching

Page 4: Functional Programming in F#

 Math   Probabilistic models

  Symbolic processing (parsing/lexing)   Symbolic differentiation   Circuit verification

Page 5: Functional Programming in F#

 Multi-paradigm language in .NET stack   Functional   Imperative

  Performance similar to C#   Interactive console   Support in Visual Studio

  Debugger   Editor

 Mono support

Page 6: Functional Programming in F#

  #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

Page 7: Functional Programming in F#

  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”

Page 8: Functional Programming in F#

 Can do it with a function

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

 Or pass a parameter

let sayHello s =   printfn s sayHello "Hello, F#!" 

Page 9: Functional Programming in 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

Page 10: Functional Programming in F#

  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) 

Page 11: Functional Programming in F#

  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

Page 12: Functional Programming in F#

  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

Page 13: Functional Programming in F#

  Tuple  Option value  Array   Sequence   List

Page 14: Functional Programming in F#

 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 ;

Page 15: Functional Programming in F#

  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” 

Page 16: Functional Programming in F#

  Your typical CLR array

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

  people.Length    yields 3

Page 17: Functional Programming in F#

  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 

Page 18: Functional Programming in F#

  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:)

Page 19: Functional Programming in F#

  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] 

Page 20: Functional Programming in F#

  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   

Page 21: Functional Programming in F#

 A non-exhaustive match will throw a MatchFailureException 

  Patterns can be grouped   match person with 

| a :: (b :: c as subGroup) ‐>   match subGroup with 

Page 22: Functional Programming in F#

 Anonymous functions   Functional composition   Partial application  Memoization

Page 23: Functional Programming in F#

 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 

Page 24: Functional Programming in F#

  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 

Page 25: Functional Programming in F#

 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]

Page 26: Functional Programming in F#

  let squareThis x =   x * x  

  let addFive x =   x + 5 

  5 |> squareThis |> addFive    yields 30

  let squareAndAddFive =   squareThis >> addFive 

  squareThisAndAddFive 5    yields 30

Page 27: Functional Programming in F#

  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)

Page 28: Functional Programming in F#

  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?

Page 29: Functional Programming in F#

  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 

Page 30: Functional Programming in F#

 Computation expressions = workflows   builder { expression }

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

Page 31: Functional Programming in F#

 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

Page 32: Functional Programming in F#

 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

Page 33: Functional Programming in F#

  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) 

Page 34: Functional Programming in F#

 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

Page 35: Functional Programming in F#

  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 

Page 36: Functional Programming in F#

  Foundations of F# Robert Pickering

  Expert F# Don Syme et al.

  F# for Scientists Jon Harrop

Page 37: Functional Programming in F#