Top Banner
F# Introduction to F# Making Programming Functional Adam Granicz [email protected] IntelliFactory, EPAM Systems
43

F# Introduction to F# Making Programming Functional Adam Granicz [email protected] IntelliFactory, EPAM Systems.

Dec 14, 2015

Download

Documents

Arely Denne
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

F#

Introduction to F#

Making Programming Functional

Adam [email protected]

IntelliFactory, EPAM Systems

Page 2: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Agenda

Motivation for functional programming (FP)

Functional programming concepts

F# - constructsFunctional, Language-oriented

F# Interactive

Page 3: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Motivation - What we would like

Programmers make mistakes so we need• More effective abstractions to express what

we need in fewer lines of code• Better type system to guard from misuse

These can give us• Abstractions/Type System

Few or no conceptual errors• Fewer LoC

Fewer bugs, better maintainability

Page 4: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Motivation - and we really wish for…

Program Synthesis

Generate programs based on a specification

A shift towards declarative programming

Eliminate programming errors for good

Program Correctness

Verify that a program fulfills its specification

Theorem provers, model checkers, etc.

Page 5: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Functional concepts

• Higher-order functions• Functions that take function parameters and/or return

functions as resultFunctions are first-class valuesAnonymous functions

• Immutability• Values are NOT mutable

• Currying• Partial function application yields a function

Page 6: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Functional concepts

• (Parametric) Polymorphism• ADTs are truly polymorphic: Map<‘t1, ‘t2>

• Type inference• No need to type annotate programs, types are

automatically inferred from use

Page 7: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Functional concepts

• Lazy vs. eager evaluation• Values are evaluated when needed versus when they

are encountered

• Recursion• Problem solving is done by recursively breaking down a

larger problem into small ones• Mutually Recursive and Recursive types• Recursive values Delayed evaluation

Page 8: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

F#

Functional, object-oriented

Strongly-typed (type-safe), type inferred, garbage collected

Succint, expressive, composable

Interoperable with any .NET language

.NET runtime support, tools, libraries

http://research.microsoft.com/fsharp/fsharp.aspx

Page 9: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

F# code sample

Page 10: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

F# constructs1 Functional

1.1 Concise syntax

1.2 Data abstractions

discriminated unions, pattern matchingpolymorphic abstract data structures

type augmentation

1.3 Control abstractions

Computation expressions (sequences, workflows)

2 Imperative (loops, mutable cells, exceptions, IO)

3 Object-oriented (classes, interfaces)

4 Language-orientedActive patterns, reflection, quotations, AST representations

Page 11: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.1 F# syntax

Traditional vs. #light syntaxIndentation matters, fewer keywords, more readable code

let f a b = let f a b =let c,d = a+b, a–b in let c,d = a+b, a-bc*d c*d

Piping functionsEncourages a more functional style, helps in type inference

let (|>) x f = f xlet (>>) f g x = g (f x)

Page 12: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.2 Abstractions – Data types

Discriminated unions

type exp = | Number of int | Add of exp * exp | Subtract of exp * exp | Multiply of exp * exp | Divide of exp * exp

Page 13: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.2 Abstractions – Data types

Pattern matching

let rec eval = function | Number i -> i | Add (e1, e2) -> eval e1 + eval e2 | Subtract (e1, e2) -> eval e1 - eval e2 | Multiply (e1, e2) -> eval e1 * eval e2 | Divide (e1, e2) -> eval e1 / eval e2

Page 14: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.2 Abstractions – Data types

Polymorphic abstract data structures

List<‘a>, Array<‘a>, Seq<‘a>Map<‘a, ‘b>, Set<‘a>, etc…

type ‘a tree = | Node of ‘a * ‘a tree * ‘a tree | Leaf

Page 15: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.2 Abstractions – Data types

TuplesPairs of values

(1, 2)((1, 2), (1, 2))([1; 2; 3], 4)

Also, n-tuples

(1, 2.0, “3”, 4I, ..)

Also, options, records, lists, arrays, sequences, etc.

Page 16: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.2 Abstractions – Type augmentation

Enriching a complex type

type trig = | Number of double | Sin of trig | Cos of trig | Add of trig * trig | Mul of trig * trig | Inv of trig with static member Tan t = Mul (Sin t, Inv (Cos

t)) static member Cot t = Mul (Cos t, Inv (Sin

t)) static member (/) (t1, t2) = Mul (t1, Inv t2) end

Page 17: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

1.2 Abstractions – Type augmentation

Augmenting existing types

module NumberTheoryExtensions = let isPrime(i) = let lim = int(sqrt(float(i))) let rec check j = j > lim or (i % j <> 0 && check (j+1)) check 2

type System.Int32 with member i.IsPrime = isPrime(i)

Page 18: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

1.2 Abstractions – Type augmentation

Augmenting existing types

> open NumberTheoryExtensions;;

> (3).IsPrime;;val it : bool = true

> (6093711).IsPrime;;val it : bool = false

Page 19: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3 Computation expressions / Workflows

Sequence expressions

building, generating, and operating on sequences, lists, and arrays

Asynchronous workflows

Probabilistic workflows

Other workflows

workflow builders + syntax desugaring

Quoted workflows quotations (language-oriented)

Page 20: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.1 Sequence expressions - building

Building sequences using range expressions> seq {0 .. 2};;val it : seq<int> = seq [ 0; 1; 2; ]

> seq {-100.0 .. 100.0};;val it : seq<double> = seq [ -100.0; -99.0; -98.0; ... ]

> seq {1I .. 1000000000000I};;val it : seq<bigint> = seq [ 0I; 1I; 2I; 3I; ... ]

Using a skip value> seq { 0 .. 2 .. 5 };;val it : seq<int> = seq [ 0; 2; 4 ]

Page 21: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.1 Sequence expressions - iterating

> let range = seq {0 .. 2 .. 6};;val range : seq<int>

> for i in range do printfn "i = %d" i;;i = 0i = 2i = 4i = 6

Page 22: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.1 Sequence expressions – aggregation

open System.IOlet rec allFiles dir = Seq.append (dir |> Directory.GetFiles) (dir |> Directory.GetDirectories |> Seq.map allFiles |> Seq.concat)

> let files = allFiles @"c:\projects";;val files : seq<string>

> files;;val it : seq<string>= seq ["c:\\projects\\AmazonSalesRank\\

AmazonSalesRank.sln"; ...

Page 23: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.1 Sequence comprehensions

let squares = seq { for i in 1 .. 100 -> (i, i*i) }

let rec allFiles2 dir = seq { for file in Directory.GetFiles dir -> file for subdir in Directory.GetDirectories dir ->> allFiles2 subdir }

Comprehensions can also be used to construct lists and arrays:

let lst = [ for i in 1 .. 100 -> (i, i*i) ]let arr = [| for i in 1 .. 100 -> (i, i*i) |]

Page 24: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.1 Turning files into on-demand sequences

let reader =seq { use reader =

new StreamReader(File.OpenRead("t.txt")) while not reader.EndOfStream do

-> reader.ReadLine() }

> reader |> Seq.take 3;;First line...Second line...Third line...

Page 25: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

1.3.1 Recursive sequences

Random walk:

let rec randomWalk k = seq { yield k yield! randomWalk (k+rnd.NextDouble()-

0.5) }

> randomWalk 10.0;;val it: seq<float> = seq [10.0; 10.23817784;

9.956430122; 10.18110362; ...]

Page 26: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.2 Asynchronous workflows – fetching pageslet museums = [ "MOMA", "http://moma.org/"; "British Museum“, "http://www..../"; "Prado", "http://museoprado.mcu.es" ]

let fetchAsync (nm, url: string) = async { do printfn "Creating request for %s..." nm let req = WebRequest.Create(url) let! resp = req.GetResponseAsync() do printfn "Getting response for %s..." nm let stream = resp.GetResponseStream() do printfn "Reading response for %s..." nm let reader = new StreamReader(stream) let! html = reader.ReadToEndAsync() do printfn "Read %d for %s..." html.Length

nm }

Page 27: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.2 Asynchronous workflows – fetching pagesfor nm,url in museums do Async.Spawn (fetchAsync(nm, url));;

> Creating request for British Museum...Creating request for MOMA...val it : unit = ()> Creating request for Prado...Getting response for Prado...Reading response for Prado...Read 1456 for Prado...Getting response for MOMA...Reading response for MOMA...Read 42918 for MOMA...Getting response for British Museum...Reading response for British Museum...Read 22131 for British Museum...

Page 28: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.2 Asynchronous workflows – file processingopen Microsoft.FSharp.Controlopen Microsoft.FSharp.Control.CommonExtensions

let numImages = 200let size = 512let numPixels = size*size

let ProcessImageAsync(i) = async { use inStream = File.OpenRead( sprintf "Image%d.tmp" i) let! pixels = inStream.ReadAsync(numPixels) let pixels' = TransformImage(pixels,i) use outStream = File.OpenWrite( sprintf "Image%d.done" i) do! outStream.WriteAsync(pixels') }

Page 29: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.2 Asynchronous workflows – file processing

let ProcessImagesAsync() = let tasks = [ for i in 1 .. numImages -> ProcessImageAsync(i) ] Async.Run (Async.Parallel tasks) |> ignore

Page 30: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

1.3.4 Other workflows - How do they work?

Computation Builders + syntax desugaring

Page 31: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

2/3 Imperative and object-oriented programming

2 Imperative (loops, mutable cells, exceptions, IO)

3 Object-oriented (classes, interfaces)

Page 32: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

4 Language-oriented programming

Active patterns

Provide a way to hide/abstract away internal representations

Reflection

QuotationsA mechanism to access the underlying syntax

representation of F# code.

LINQ

Page 33: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

4.1 Active patterns

Extensible pattern matching

Provide a way to hide/abstract away internal representations

open Microsoft.FSharp.Math

let (|Rect|) (x:complex) = (x.RealPart, x.ImaginaryPart)

let (|Polar|) (x:complex) = (x.Magnitude, x.Phase)

Page 34: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

4.1 Active patterns

> let c = Complex.mkRect(3.0, 4.0);;val c : complex> c;;val it : complex = 3.0r+4.0i

> match c with| Rect(x,y) -> printfn "x = %g, y = %g" x y;;x = 3, y = 4val it : unit = ()

> match c with| Polar(x,y) -> printfn "x = %g, y = %g" x y;;x = 5.0, y = 0.927295val it : unit = ()

Page 35: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

4.2 Reflection

Obtaining representations of assemblies, type definitions, and member signatures

Via .NET reflection API

> let intListType = typeof<int list>;;val intListType : System.Type

> intListType.FullName;;val it : string =

"Microsoft.FSharp.Collections.List`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"

Page 36: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

4.3 Quotations

A mechanism to access the underlying syntax representation of F# code.

let plusExpr = <@ 1 + 1 @>;;val plusExpr : Expr<int>

> plusExpr;;val it : Expr<int>= <@ Microsoft.FSharp.Core.Operators.op_Addition

(Int32 1) (Int32 1) @>

Page 37: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

4.4 Quotations and LINQ – In-memory objects

In-memory objects / collections

Native support via aggregate functions

let select = Seq.maplet where = Seq.filterlet people = [| ("Joe", 27, "Sales"); ("Rick", 35, "Marketing"); ("Mark", 40, "Sales"); ("Rob", 31, "Administration"); ("Bob", 34, "Marketing") |]let namesR = people |> select (fun (name, age, dept) -> name) |> where (fun name -> name.StartsWith "R")

Page 38: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

4.4 Quotations and LINQ – XML

XMLFunctional construction of XML documents

mutation

Page 39: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Edit text and revise your documents

4.4 Quotations and LINQ – Linq2Sql

Access to query syntax via F# quotations

Transform F# quotations to LINQ expressions

val SQL : Expr<'a> -> 'a

let res = SQL <@ { for emp in (#db.Employees) when emp.BirthDate.Value.Year > 1960 && emp.LastName.StartsWith "S" -> (emp.FirstName, emp.LastName) } @> |> take 5

for (first, last) in res doprintfn "%s %s" first last

Page 40: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

F# Interactive (fsi.exe)

Command-line

Page 41: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

F# Interactive (fsi.exe)

Visual Studio plug-in

Page 42: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Questions?

Page 43: F# Introduction to F# Making Programming Functional Adam Granicz granicz.adam@intellifactory.com IntelliFactory, EPAM Systems.

Reading more about F#

Expert F#Apress – 2007 Dec 7

Don Syme, Adam Granicz, Antonio Cisternino