an introduction to f# · program.fs namespace widgets ... [""; ... //find the sum of all...

31
About Me – Sushant Bhatia, From India/Malawi, Work at Citation Technologies Inc, an Environmental Health & Safety company with Compliance Why I chose to do this talk – No one else was doing functional programming. I wanted to learn F#. Just started a few weeks ago. 1

Upload: trinhque

Post on 05-Jul-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

About Me – Sushant Bhatia, From India/Malawi, Work at Citation Technologies Inc, an Environmental Health & Safety company with Compliance Why I chose to do this talk – No one else was doing functional programming. I wanted to learn F#. Just started a few weeks ago.

1

Functional programming is essential to know Being added to C# and .Net (generics, lambdas) Useful for developing at a higher level. Add to your tool belt Fun

2

Raffle at the end

3

Open VS 2011 VB Programmers? You just got Iterators, Call hierarchy & Global with .Net 4.5 New Project & talk about 3 different project types Create F# Application (Property change from Client Profile to full blown profile) Add a New Item Signature File – describes namespace, modules, types & members in corresponding implementation file Add a new .fs file Show UP / DOWN of file order. Compilation order = type inference Remove added .fs file Demo Hello World let msg = “Hello World” Build Run -> Nothing happens Talk about F# Interactive (REPL – Read Evaluate Print Loop) (ALT + ENTER)

4

Type msg;; in Interactive Add print “%s” msg Run app (F5) Clear Demo Hello World 2 open System Console.WriteLine “Hello World” (F5) clear Talk about ‘let’ and how F# values are immutable F# is case sensitive & whitespace matters Comments -> //, ///, (* *) Demo Greatest Common Denominator

let rec gcd x y = if y = 0 then x else gcd y (x % y)

Hover over gcd defintion to show inference occurs printfn "%i" (gcd 100 6) clear Demo Other things in F# int, float, BigInt (I) 2 + 2;; shows val it : int = 4 (this is an unnamed expression)

let my x = if x > 5 then printfn "Cool!" else let db = "Something" printfn "%i %s" x db ()

clear

4

5

Unit is a concrete representation of void Ignore function swallows a functions return value Tuples provide a convenient way to return multiple values from a function Tuples – fst, snd to get values from a tuple. Can also bind as such let myTuple = (1, 2, 3) let x, y, z = myTuple let divRem a b = let x = a / b let y = a % b (x, y) let s = divRem 10 2 Lists – Cons (:: ) – adds to head of list, append (@) – joins two lists List ranges created [1 .. 10], [1 .. 10 .. 100] List comprehension – use yield statement within [ and ] Option – represents a value that may or may not exist let resolve x = match x with

6

| Option.None -> "Zero" | Option.Some(30) -> "What what what" | _ -> "Meh" // try 6 and 633 let isThereA5 = List.tryFind (fun x -> x%633 = 0) [10 .. 10 .. 100] |> resolve

6

For multi file projects, code must be organized into modules or namespaces Create a second fs file. Program.fs

namespace Widgets module Program = let Sqr x = x * x module NotMath = let Name = "Sushant Bhatia" type Suit = | Club | Diamond | Heart | Spade | Octagon

File1.fs

7

module File1 let result x = Widgets.Program.Sqr x |> printfn "%A" printfn "%s" Widgets.Program.NotMath.Name result 5; let myCardType = Widgets.Suit.Club let getMatch cardType = match cardType with | Widgets.Club -> "Its a club" | Widgets.Diamond -> "its a diamond" | Widgets.Heart -> "Its a heart" | Widgets.Spade -> "Its a spade" | _ -> "Its a what? Cheater!" (getMatch myCardType) |> printfn "%s"

Namespaces cannot directly contain values and functions. Values and functions must be included in modules, and modules are included in namespaces. Namespaces can contain types, modules.

7

DEMO – Forward composition operator joins functions together let sqr (x : int) = x * x let toString (x : int) = x.ToString() let strLen (x : string) = x.Length let lenOfSqr = sqr >> toString >> strLen sqr 100 lenOfSqr 100 There is also a Pipe Backward (<|) and backward composition (<<) operator

8

Rules are checked in the order they are declared. NoMatch -> MatchFailureException Compiler will issue warning when matches are missing SEE DEMO FROM Module & Namespace

9

SEE DEMO FROM Module & Namespace DEMO – BINARY TREES

type BinaryTree = | Node of int * BinaryTree * BinaryTree | Empty let rec printInOrder tree = match tree with | Node (data, left, right) -> printInOrder left printfn "Node %d" data printInOrder right | Empty -> () (* 2 / \ 1 4 / \ 3 5

10

*) let example = Node(2, Node(1, Empty, Empty), Node(4, Node(3, Empty, Empty), Node(5, Empty, Empty) ) ) printInOrder example

10

11

Program is a description of a specific computation Ignore how & focus on what Program is a black box for obtaining output from input ∴ Program is like a function

12

Originated with Lambda calculus = formal system developed in 1930s investigate function definition, application & recursion

13

Still quite complex so lets break it down

14

Treat functions as first class objects.

16

17

An expression is said to be referentially transparent if it can be replaced with its value without changing the behavior of a program. Memoization is optimization by having function calls avoid repeating the calculations of results for previously processed inputs. DEMO: Memoization open System let sqr i : int = i * i let memoize f = let cache = ref Map.empty fun x -> match (!cache).TryFind(x) with | Some res -> res | None -> let res = f x cache := (!cache).Add(x,res) res let memoizedAppend =

18

memoize (fun input -> printfn "Working out the value for '%A'" input String.concat ", " [ for i in 0 .. input -> sprintf "%d: %i" i (sqr i) ]) Console.WriteLine(memoizedAppend(10)) Console.WriteLine("\r\n----\r\n") Console.WriteLine(memoizedAppend(10)) Console.WriteLine("\r\n----\r\n") Console.WriteLine(memoizedAppend(5)) Console.WriteLine("\r\n----\r\n") Console.WriteLine(memoizedAppend(10))

18

Using recursion can be expensive for large numbers of iterations due to declaring the stack over and over. Process is terminated due to StackOverflowException. For this purpose, know when to use Tail Recursion Tail calls drop the current stack frame before making the recursive call. Thus function will execute faster, indefinitely and no stackoverflowexception. The CLR has an IL instruction specifically to help with tail recursion: the tail. IL prefix. The tail. instruction tells the CLR it can discard the caller’s method state prior to making the associated call. DEMO: Fibonacci let rec fib n = if n < 2I then 1I else fib (n-2I) + fib(n-1I) let fibTail = Seq.unfold (fun (x, y) -> Some(x, (y, x+y)) ) (0I,1I) fibTail |> Seq.nth 50000

19

Currying transforms a function that has more than 1 parameter into a series of embedded functions each with 1 parameter. Can only curry parameters from left to right DEMO: sizeOfDir open System.IO let sizeOfDir folder pattern = let getFiles folder = Directory.GetFiles(folder, pattern, SearchOption.AllDirectories) let totalSize = folder |> getFiles |> Array.map (fun file -> new FileInfo(file)) |> Array.map (fun info -> info.Length) |> Array.sum totalSize let DellFolder = sizeOfDir "C:\\DELL" DellFolder "*.txt"

20

DEMO: Netflix open System.Data.Services.Client open Microsoft.FSharp.Data.TypeProviders // Use the OData type provider to access the Netflix catalog. [<Generate>] type Catalog = ODataService<"http://odata.netflix.com/Catalog/"> let netflix = Catalog.GetDataContext() // Query Netflix for all titles containing the word "Avatar" let titles = query { for t in netflix.Titles do where (t.Name.Contains "naruto") } titles |> Seq.iter (fun i -> printfn "%A - %s %i" i.Id i.Name i.Awards.Count)

21

Console.WriteLine(memoizedAppend(10)) Console.WriteLine("\r\n----\r\n") Console.WriteLine(memoizedAppend(10)) Console.WriteLine("\r\n----\r\n") Console.WriteLine(memoizedAppend(5)) Console.WriteLine("\r\n----\r\n") Console.WriteLine(memoizedAppend(10)) DEMO: Units of Measure [<Measure>] type kg [<Measure>] type s [<Measure>] type m [<Measure>] type N = (kg * m)/(s^2) let gravityOnEarth = 9.81<m/(s^2)> let dropHeight = 1000.0<m> let impactSpeed = sqrt(2.0 * gravityOnEarth * dropHeight) let force :float<N> = 80.0<kg> * gravityOnEarth DEMO – ASYNC open System open System.Net open System.Text.RegularExpressions let websites = ["http://www.weather.gov"; "http://msdn.microsoft.com/en-us/"; "http://fsharp-euler.wikispaces.com"] let regTitle = new Regex(@"\<title\>([^\<]+)\</title\>") let WriteLinePageTitle result = printfn "%A" (regTitle.Match result).Groups.[0].Value let AsyncIntroSingle website = async { let client = new WebClient() let! result = client.AsyncDownloadString(Uri(website))

21

do WriteLinePageTitle result } |> Async.StartImmediate websites |> List.iter (fun x -> AsyncIntroSingle x)

21

http://projecteuler.net/problems http://fsharp-euler.wikispaces.com/ //If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. //Find the sum of all the multiples of 3 or 5 below 1000. let lst = [1..1000] |> List.filter (fun x -> x%3 = 0 || x%5 = 0) |> List.sum //Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: // 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... //By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. let fibTail = Seq.unfold (fun (x, y) -> Some(x, (y, x+y)) ) (0I,1I) let problem2 = fibTail |> Seq.takeWhile (fun x -> x < 4000000I) |> Seq.sumBy (fun x -> if x%2I = 0I then x else 0I)

22

Read Practice Solve real world problems with it

23

24