+ All Categories
Home > Documents > F# Introduction to F# Making Programming Functional Adam Granicz [email protected]...

F# Introduction to F# Making Programming Functional Adam Granicz [email protected]...

Date post: 14-Dec-2015
Category:
Upload: arely-denne
View: 232 times
Download: 0 times
Share this document with a friend
43
F# Introduction to F# Making Programming Functional Adam Granicz [email protected] IntelliFactory, EPAM Systems
Transcript

F#

Introduction to F#

Making Programming Functional

Adam [email protected]

IntelliFactory, EPAM Systems

Agenda

Motivation for functional programming (FP)

Functional programming concepts

F# - constructsFunctional, Language-oriented

F# Interactive

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

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.

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

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

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

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

Edit text and revise your documents

F# code sample

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

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)

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

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

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

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.

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

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)

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

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)

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 ]

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

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"; ...

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

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...

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; ...]

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 }

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...

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') }

1.3.2 Asynchronous workflows – file processing

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

1.3.4 Other workflows - How do they work?

Computation Builders + syntax desugaring

2/3 Imperative and object-oriented programming

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

3 Object-oriented (classes, interfaces)

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

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)

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 = ()

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]]"

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

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

Edit text and revise your documents

4.4 Quotations and LINQ – XML

XMLFunctional construction of XML documents

mutation

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

F# Interactive (fsi.exe)

Command-line

F# Interactive (fsi.exe)

Visual Studio plug-in

Questions?

Reading more about F#

Expert F#Apress – 2007 Dec 7

Don Syme, Adam Granicz, Antonio Cisternino


Recommended