Concepts of programming languages F# Tim Zoet, Zino Onomiwo, - - PowerPoint PPT Presentation

concepts of programming languages
SMART_READER_LITE
LIVE PREVIEW

Concepts of programming languages F# Tim Zoet, Zino Onomiwo, - - PowerPoint PPT Presentation

[Faculty of Science Information and Computing Sciences] 1 Concepts of programming languages F# Tim Zoet, Zino Onomiwo, Martijn Boom, Rik van Toor [Faculty of Science Information and Computing Sciences] 2 Background Don Syme


slide-1
SLIDE 1

[Faculty of Science Information and Computing Sciences] 1

Concepts of programming languages

F#

Tim Zoet, Zino Onomiwo, Martijn Boom, Rik van Toor

slide-2
SLIDE 2

[Faculty of Science Information and Computing Sciences] 2

Background

▶ Don Syme ▶ Microsoft Research ▶ Recent development by the F# Software Foundation ▶ Microsoft develops the Visual F# tools

slide-3
SLIDE 3

[Faculty of Science Information and Computing Sciences] 3

What is F#

▶ A fjrst-class member of the .NET Framework. ▶ Strongly related to ML and OCaml. ▶ A hybrid language ▶ Integration within Visual Studio

slide-4
SLIDE 4

[Faculty of Science Information and Computing Sciences] 4

Programming in F#

Hello World

let a_string = "World" printfn "Hello %s" a_string

slide-5
SLIDE 5

[Faculty of Science Information and Computing Sciences] 5

Types and variables

type name = string let author: name = "infinite monkey" What features regarding types are supported in F#?

slide-6
SLIDE 6

[Faculty of Science Information and Computing Sciences] 6

Tuples, structures and more.

Tuples:

type tuple = int * string let tuple = (1, “hi!”) // Comma separated

Records

type Person = {Name:string; Age:int; Status:string} // named fields, semicolon separated let celebrity = {Name=”Gordon”, Age=49, Status=”single”}

slide-7
SLIDE 7

[Faculty of Science Information and Computing Sciences] 7

Tuples, structures and more.

Union

type Person = | CatPerson of string | DogPerson of string let martijn = DogPerson “Martijn”

slide-8
SLIDE 8

[Faculty of Science Information and Computing Sciences] 8

Tuples, structures and more.

Recursive structures and unions:

type 'a union = A 'a | B 'a type 'a tree = |EmptyTree | Node of 'a * 'a tree * 'a tree

slide-9
SLIDE 9

[Faculty of Science Information and Computing Sciences] 9

Tuples, structures and more.

Structures:

type Cat = struct val Name: name; val Fur: color val Env: environment new (n, f, e) = {Name = n; Fur = f; Env = e} end let cat: Cat = new Cat("Ottoman", RED, BLOCKCHAIN)

slide-10
SLIDE 10

[Faculty of Science Information and Computing Sciences] 10

Lists and arrays

Arrays

Fixed size and mutable let arr = [|1; 2; 3; 4; 5|] let arr2 = [|1.0; 2; 3|] // Gives an error let arr3 = [|for i in 1 .. 100 -> i * (i+1)|] printfn “%d” arr.[0] // prints 2 printfn “%A” array // print [1; 2; 3; 4; 5]

slide-11
SLIDE 11

[Faculty of Science Information and Computing Sciences] 11

Lists and arrays

Lists

singly linked list and immutable let lissy = [1; 2; 3] let lissy2= 1::[2 … 8999] @ [1] let lissy3= [for i in 1 .. 100 -> i * (i+1)] let rec sum list = match list with | head :: tail -> head + sum tail | [] -> 0

slide-12
SLIDE 12

[Faculty of Science Information and Computing Sciences] 12

Functions

let add x y = x + y let sumOfSquares n = [1..n] |> List.map square |> List.sum sumOfSquares 100 let adderGenerator = fun x -> (fun y -> x + y)

slide-13
SLIDE 13

[Faculty of Science Information and Computing Sciences] 13

Classes

type Exam(student, subject, grade) = member this.Student = student member this.Subject = subject member this.Grade = grade// public member let stressLevel = 100 //private member new Exam(“Socrates”, “Philosophy for dummies”, 10)

slide-14
SLIDE 14

[Faculty of Science Information and Computing Sciences] 14

Pattern matching

match x with | case1 -> … | case2 -> … | _ -> …

slide-15
SLIDE 15

[Faculty of Science Information and Computing Sciences] 15

let patternMatcher input = match input with | “a” -> printfn “Case 1” | “b” -> printfn “Case 2” | _

  • > printfn “Default”

patternMatcher “a” patternMatcher “b” patternMatcher “c”

slide-16
SLIDE 16

[Faculty of Science Information and Computing Sciences] 16

let listSummary list = match list with | []

  • > printfn "empty array"

| [x]

  • > printfn "one element: %s" x

| [x;y] -> printfn "two elements” | _

  • > printfn "multiple elements"
slide-17
SLIDE 17

[Faculty of Science Information and Computing Sciences] 17

Async

Ruin code in parallel let motivationLevel (lvl, target) = async { printfn "Motivating %s till %i \%" target lvl do! Async.Sleep percentage printfn "%s is %i \% motivated" target lvl } [(101, “Tim”), (65, “Rik”)] |> List.map motivationLevel |> Async.Parallel |> Async.RunSynchronously

slide-18
SLIDE 18

[Faculty of Science Information and Computing Sciences] 18

[<Measure>] type cm [<Measure>] type meter let cmPerMeter = 10<cm/meter> let distanceToHomeCm = 100<cm> let distanceToHomeM = distanceToHomeCm * cmPerMeter let otherConvert v: float<_> = match v with | :? float<cm> -> v * cmPerMeter | :? float<meter> -> v<meter>

slide-19
SLIDE 19

[Faculty of Science Information and Computing Sciences] 19

Type inference

▶ Using amas-Milner’s Algorithm ▶ Look at the literals ▶ Look at the functions and other values something interacts

with

▶ Look at any explicit type constraints ▶ If there are no constraints anywhere, automatically

generalize to generic types

slide-20
SLIDE 20

[Faculty of Science Information and Computing Sciences] 20

Relation to other languages

slide-21
SLIDE 21

[Faculty of Science Information and Computing Sciences] 21

Compared to C#

▶ Concise

public static IEnumerable<T> QuickSort<T>(this IEnumerable<T> values) where T: IComparable { if (values == null || !values.Any()) return new List<T>(); var pivot = values.First(); var rest = values.Skip(1); var smallerElements = rest.Where(i => i.CompareTo(pivot) < 0).QuickSort(); var largerElements = rest.Where(i => i.CompareTo(pivot) >= 0).QuickSort(); return smallerElements.Concat(new List<T> { pivot }).Concat(largerElements); }

slide-22
SLIDE 22

[Faculty of Science Information and Computing Sciences] 22

let rec quicksort = function | [] -> [] | pivot::rest -> let smaller,larger = List.partition ((>=) pivot) rest List.concat [quicksort smaller; [pivot]; quicksort larger]

▶ Little coding noise ▶ Pattern matching ▶ Functional List module

slide-23
SLIDE 23

[Faculty of Science Information and Computing Sciences] 23

Type inference

let AStringFunction = "It is implied I return a string" let AStringFunction :string = "It is made explicit I return a string" string AnotherStringFunction(){ return "I'm a string function as well"; }

slide-24
SLIDE 24

[Faculty of Science Information and Computing Sciences] 24

Domain-driven design

type StreetAddress = {Line1:string; Line2:string; Line3:string } type ZipCode = ZipCode of string type StateAbbrev = StateAbbrev of string type ZipAndState = {State:StateAbbrev; Zip:ZipCode } type USAddress = {Street:StreetAddress; Region:ZipAndState} type UKPostCode = PostCode of string type UKAddress = {Street:StreetAddress; Region:UKPostCode}

slide-25
SLIDE 25

[Faculty of Science Information and Computing Sciences] 25

Domain-driven design

type InternationalAddress = { Street:StreetAddress; Region:string; CountryName:string} type Address = USAddress | UKAddress | InternationalAddress

slide-26
SLIDE 26

[Faculty of Science Information and Computing Sciences] 26

Interoperability with C#

namespace interoperability.fsharp type Beverage (brand:string, volume:int) = member this.Brand = brand member this.Volume = volume

slide-27
SLIDE 27

[Faculty of Science Information and Computing Sciences] 27

using interoperability.fsharp; namespace interoperability.csharp { class Program { static void Main(string[] args) { //from record to class Beverage coke = new Beverage("Coca Cola", 330); Console.WriteLine(coke.name + “ “ + coke.Volume); } } }

slide-28
SLIDE 28

[Faculty of Science Information and Computing Sciences] 28

using interoperability.fsharp; namespace interoperability.csharp { class Program { static void Main(string[] args) { //from record to class Beverage coke = new Beverage("Coca Cola", 330); Console.WriteLine(coke.name + “ “ + coke.Volume); } } }

▶ output = “Coca Cola 330”

slide-29
SLIDE 29

[Faculty of Science Information and Computing Sciences] 29

namespace interoperability.fsharp type Beverage (brand:string, volume:int) = member this.Brand = brand member this.Volume = volume module BeverageTasks = let drink (x:Beverage) = Beverage(x.Brand, 0)

slide-30
SLIDE 30

[Faculty of Science Information and Computing Sciences] 30

using interoperability.fsharp; namespace interoperability.csharp { class Program { static void Main(string[] args) { //from record to class Beverage coke = new Beverage("Coca Cola", 330); //from module to static class coke = BeverageTasks.drink(coke) Console.WriteLine(coke.name + “ “ + coke.Volume); } } }

slide-31
SLIDE 31

[Faculty of Science Information and Computing Sciences] 31

using interoperability.fsharp; namespace interoperability.csharp { class Program { static void Main(string[] args) { //from record to class Beverage coke = new Beverage("Coca Cola", 330); //from module to static class coke = BeverageTasks.drink(coke); Console.WriteLine(coke.name + “ “ + coke.Volume); } } }

  • utput = “Coca Cola 0”
slide-32
SLIDE 32

[Faculty of Science Information and Computing Sciences] 32

namespace interoperability.fsharp type Beverage (brand:string, volume:int) = member this.Brand = brand member this.Volume = volume module BeverageTasks = let drink (x:Beverage) = Beverage(x.Brand, 0) let mutable message = "Wasn't I supposed to be functional?"

slide-33
SLIDE 33

[Faculty of Science Information and Computing Sciences] 33

using interoperability.fsharp; namespace interoperability.csharp { class Program { static void Main(string[] args) { //from record to class Beverage coke = new Beverage("Coca Cola", 330); Console.WriteLine(BeverageTasks.message); BeverageTasks.message = "Not anymore!"; Console.WriteLine(BeverageTasks.message); } } }

slide-34
SLIDE 34

[Faculty of Science Information and Computing Sciences] 34

using interoperability.fsharp; namespace interoperability.csharp { class Program { static void Main(string[] args) { //from record to class Beverage coke = new Beverage("Coca Cola", 330); Console.WriteLine(BeverageTasks.message); BeverageTasks.message = "Not anymore!"; Console.WriteLine(BeverageTasks.message); } } }

▶ “Wasn’t I supposed to be functional?” ▶ “Not anymore!”

slide-35
SLIDE 35

[Faculty of Science Information and Computing Sciences] 35

type Taste = | Sweet = 'a' | Sour = 'b' | Bitter = 'c' | Salty = 'd' Taste cokeTaste = Taste.Sweet;

slide-36
SLIDE 36

[Faculty of Science Information and Computing Sciences] 36

type Taste = | Sweet = 'a' | Sour = 'b' | Bitter = 'c' | Salty = 'd' Taste cokeTaste = Taste.Sweet;

▶ error = ‘Taste.Sweet’ is not supported by the language

slide-37
SLIDE 37

[Faculty of Science Information and Computing Sciences] 37

Relation to Haskell

▶ Both are functional languages ▶ Both have cool logos ▶ Similar way of thinking while coding

slide-38
SLIDE 38

[Faculty of Science Information and Computing Sciences] 38

Relation to Haskell

F#

▶ Functional fjrst

Haskell

▶ Purely functional

slide-39
SLIDE 39

[Faculty of Science Information and Computing Sciences] 39

Polymorphism

F#

▶ Does not really exist

Haskell

▶ Exists

slide-40
SLIDE 40

[Faculty of Science Information and Computing Sciences] 40

Polymorphism

Haskell (in GHCi):

> let square x = x * x > square 2 4 > square 2.0 4.0

slide-41
SLIDE 41

[Faculty of Science Information and Computing Sciences] 41

Polymorphism

F# (in fsharpi):

> let square x = x * x;; > square 2;; val it : int = 4 > square 2.0;; error FS0001: This expression was expected to have type int Caused by Type Inference.

slide-42
SLIDE 42

[Faculty of Science Information and Computing Sciences] 42

Polymorphism

To override: > let inline square x = x * x;; > square 2;; val it : int = 4 > square 2.0;; val it : float = 4.0

slide-43
SLIDE 43

[Faculty of Science Information and Computing Sciences] 43

Polymorphism - More diffjcult

In Haskell: class Showable a where shw :: a -> String data A = A String data B = B Int instance Showable A where shw (A s) = s instance Showable B where shw (B i) = show i

slide-44
SLIDE 44

[Faculty of Science Information and Computing Sciences] 44

Polymorphism - More diffjcult

In F#: type A = { thing: int } with static member show a = sprintf "%A" a type B = { label: string } with static member show b = sprintf "%A" b let inline show (x:^t) = (^t: (static member show: ^t -> string) (x)) This is called statically resolved type constraints

slide-45
SLIDE 45

[Faculty of Science Information and Computing Sciences] 45

Polymorphism - More diffjcult

An alternative in F#: type A = { thing: int } type B = { label: string } type ThingThatShows = static member show(x:A) = sprintf "%A" x static member show(x:B) = sprintf "%A" x This is called static member overloading

slide-46
SLIDE 46

[Faculty of Science Information and Computing Sciences] 46

Currying

Works the same way in F# and Haskell. let f a b = something is internally converted to let f a = let g b = something g

slide-47
SLIDE 47

[Faculty of Science Information and Computing Sciences] 47

Currying

This also means that the type signature a -> b -> c is equal to a -> (b -> c) Just like it would be in Haskell.

slide-48
SLIDE 48

[Faculty of Science Information and Computing Sciences] 48

Partial application

Consider f :: int -> int -> int. Because of the currying mechanism, f 2 will be of type int -> int. Partial applications works the same way in F# and Haskell.

slide-49
SLIDE 49

[Faculty of Science Information and Computing Sciences] 49

Function associativity

x y z is equal to (x y) z. Just like in Haskell, function application is left associative. Operators exist to help: x <| y z is equal to x (y z), limiting the number of parentheses. The same operator but inverted exists as well: x y |> z is equal to z (x y).

slide-50
SLIDE 50

[Faculty of Science Information and Computing Sciences] 50

Evaluation

Haskell uses lazy evaluation. F# uses eager evaluation by default, unless explicitly specifjed

  • therwise.

Example: let always5 x = 5

slide-51
SLIDE 51

[Faculty of Science Information and Computing Sciences] 51

Evaluation

Haskell:

  • - Will just return 5

always5 $ map sqrt [1.0..1000000000.0] F#: //Will take a long time always5 <| List.map sqrt [1.0..1000000000.0] //Will just return 5 always5 <| lazy(List.map sqrt [1.0..1000000000.0])

slide-52
SLIDE 52

[Faculty of Science Information and Computing Sciences] 52

Syntax

F#:

▶ A little more verbose than Haskell ▶ More keywords than Haskell

Haskell:

▶ Amazing ▶ The best

slide-53
SLIDE 53

[Faculty of Science Information and Computing Sciences] 53

Syntax - examples

▶ let let let let let let let let let let let let let. ▶ You will type let a lot in F#.

slide-54
SLIDE 54

[Faculty of Science Information and Computing Sciences] 54

Syntax - examples

F#

let rec sum list = match list with | head :: tail -> head + sum tail | [] -> 0

Haskell

sum [] = 0 sum (head:tail) = head + sum tail

▶ Explicit rec

slide-55
SLIDE 55

[Faculty of Science Information and Computing Sciences] 55

Type providers

‘Information-rich programming’

slide-56
SLIDE 56

[Faculty of Science Information and Computing Sciences] 56

Making programming as easy as possible.

slide-57
SLIDE 57

[Faculty of Science Information and Computing Sciences] 57

Coincidentally the subject of our research project.

slide-58
SLIDE 58

[Faculty of Science Information and Computing Sciences] 58

▶ Generate types and add them to your project based on

some source containing type defjnitions.

▶ Type checking. ▶ Auto-completion. ▶ Integrated connection handling.

slide-59
SLIDE 59

[Faculty of Science Information and Computing Sciences] 59

Improvement on:

▶ Manual implementation ▶ Code generation ▶ (Runtime generation)

slide-60
SLIDE 60

[Faculty of Science Information and Computing Sciences] 60

Manual implementation

▶ Write F# type for every type in your information space.

slide-61
SLIDE 61

[Faculty of Science Information and Computing Sciences] 61

Manual implementation

▶ Updates of information space? Manual work… ▶ Not doable in real world applications with thousands of

types.

slide-62
SLIDE 62

[Faculty of Science Information and Computing Sciences] 62

Code generation

▶ Generate F# types from e.g. a fjle containing type

defjnitions.

slide-63
SLIDE 63

[Faculty of Science Information and Computing Sciences] 63

Code generation

▶ Rerun when information space changes.

slide-64
SLIDE 64

[Faculty of Science Information and Computing Sciences] 64

Example CSV

name age length Alice 42 1.69 Bob 24 1.78 Eve 32 1.75 … … …

slide-65
SLIDE 65

[Faculty of Science Information and Computing Sciences] 65

type UserFile = CsvProvider<"someFile.csv"> let userFileInstance = UserFile.Load("sameOrMaybeAnotherFile.csv") print userFileInstance.firstRow.name

slide-66
SLIDE 66

[Faculty of Science Information and Computing Sciences] 66

type UserFile = CsvProvider<"someFile.csv"> Generate types from some fjle containing (sample) data.

slide-67
SLIDE 67

[Faculty of Science Information and Computing Sciences] 67

let userFileInstance = UserFile.Load("sameOrMaybeAnotherFile.csv") print userFileInstance.firstRow.name Create instance and access data. ‘Normal code’.

slide-68
SLIDE 68

[Faculty of Science Information and Computing Sciences] 68

What about databases?

type DatabaseSource = DatabaseProvider<"www.mydatabase.com/types"> let databaseConnection = DatabaseSource.Connect("www.mydatabase.com") // ...perform queries on databaseConnection

slide-69
SLIDE 69

[Faculty of Science Information and Computing Sciences] 69

Great… so?

▶ Type checking. ▶ Auto-completion. ▶ Connections/fjles etc. ▶ Extend types.

We could already do all these things.

slide-70
SLIDE 70

[Faculty of Science Information and Computing Sciences] 70

But… it’s all in one place.

slide-71
SLIDE 71

[Faculty of Science Information and Computing Sciences] 71

More: regular expressions.

type T = RegexTyped< @"(?<AreaCode>^\d{3})- (?<PhoneNumber>\d{3}-\d{4}$)"> let reg = T() let result = T.IsMatch("425-555-2345") Limitation: string has to be known at compile-time.

slide-72
SLIDE 72

[Faculty of Science Information and Computing Sciences] 72

How do you actually write a type provider?

[<TypeProvider>] type CsvProvider(config: TypeProviderConfig) as this = //

slide-73
SLIDE 73

[Faculty of Science Information and Computing Sciences] 73

  • 1. Add static parameters to the type provider.
  • 2. Call ProvidedTypeDefjnition to provide the base type.
  • 3. Add methods such as Load and members such as Rows to

the base type.

  • 4. Open the sample fjle.
  • 5. Infer the type from each column and add these types.
slide-74
SLIDE 74

[Faculty of Science Information and Computing Sciences] 74

Biggest limitation.

Static parameters can only be primitive types.

slide-75
SLIDE 75

[Faculty of Science Information and Computing Sciences] 75

Thank you for your attention

Please feel free to ask any questions.