An introduction to F# Bogdan Brinzarea-Iamandi Banca Romaneasca 22 February 2010
TopicCovered Today History From imperative to functional Fundamentals Data structures Pattern matching Immutability vs. Mutability Object Oriented Programming Async and Parallel Programming25 February 2010 Unit testing25 February 2010
“The most original new face in computer languages since Bjarne Stroustrup developed C++ in the early 1980‘s” of-the-week/
Functional Programming Language Will ship with Visual Studio 2010 Deep roots in OCaml ( ) Developed by Microsoft Research
Succinctness Type safety Type inference Expressivity Scripting Performance Seamless integration with.NET
Functional programming Imperative programming Object oriented programming Scripted programming
Well suited for: Technical programming Algorithmic programming Parallel programming Asynchronous programming Explorative programming Financial computing
static IEnumerable Fibonacci { get{ int i = 1; int j = 2; while (true) { int n = i; yield return n; i = j; j = j + n; }
let fibs = Seq.unfold (fun (i,j) -> Some(i,(j,i+j))) (1,2)
Much more like our mind thinks Easy to grasp for scientists Pure functional programming has no side effects - immutability Highly parallelizable Powerful function support with currying and composition
C# 3.0 already has lambda expressions, anonymous functions, first class functions, anonymous types Matthew Podwysocki - Functional C# Bart de Smet Luca Bolognese
Variable and assignment as main operations In C# value types are immutable F# is not pure functional as it has Flow control (for, while, if) Mutable keyword Reference cells Arrays
CharacteristicImperativeFunctional Programmer focusHow to perform tasks (algorithms) and how to track changes in state. What information is desired and what transformations are required. State changesImportant.Non-existent. Order of executionImportant.Low importance. Primary flow controlLoops, conditionals, and function (method) calls. Function calls, including recursion. Primary manipulation unit Instances of structures or classes. Functions as first-class objects and data collections. MSDN Library
Lightweight syntax Makes whitespaces significant Lets you leave out tokens such as begin end ; ;; in Makes code more readable and concise
printfn "Hello world!"
// define a value let message ="Hello world!“ // define a function value let sqr x = x*x Binds forever a value or function value to an identifier DOES NOT assign a value to an identifier The identifiers are immutable The compiler infers the types
F# is statically typed The compiler infers the type for all variables and functions We need to specify only when it cannot be deduced Every value and expression has a definite type at compile time
Automatic generalization - if the type is not specified it is inferred as generic // 'a -> 'b -> 'a * 'b let pair x y = (x, y)
The return type of a function is determined by the type of the last expression in the function. // int->int->int let add1 x y = x + y + 1 // float->float->float let add10 x y = x + y + 1.0
We can give the compiler a little help // help inferring the type let (message:string) = "Hello world!" let add (x:float) (y:float) = x+y let sum = add
Can be used as parameters to other functions let squares = Array.map (fun x->x*x) [|0..10|]
Functions are not recursive by default Make sure the recursively function ends Use the rec keyword together with let let rec Fibonacci n = if n<2 then n else Fibonacci n-1 + Fibonacci n-2
Named after Haskell Curry A function that calls another function and returns a function or A partial function let add x y = x + y let add5 = add 5 let result = add5 6
Indentation matters let SquareAndSum x y = let sqr x = x * x sqr x + sqr y
Arithmetic operatorsDescription x + yAddition x – ySubtraction x * yMultiplication x / yDivision x % yModulus x ** yPower of Boolean operatorDescription notBoolean NOT ||Boolean OR &&Boolean AND
F# typeC# typeExample boolBooleantrue byteByte45y sbyteSByte45uy int16Int1645s uint16UInt1645us intInt3245 uintUInt3245u int64Int6445L uint64UInt6445UL charChar‘c’ decimalDecimal45M stringString“A string” unitnot applicable()
Scientists love it Composition f(g(x)) g >> f Pipelines take an input of a function and pass it to the next one input |> function 1 |> function 2
A group of unnamed but ordered values Can contain different types In.NET System.Tuple
All elements of the array must have the same type Elements are mutable A lot of helper functions to choose from (map, filter, iter etc.) let array1 = [| 0; 1; 2 |] let array2 = [| |] let array3 = [| for i in > i |]
A series of elements all of same (base) type Lists are immutable :: (cons operator) adds an element to the head of the list concatenates lists Head, Tail properties A lot of helper functions to choose from ( head, tail, nth, map, iter, filter ) let list1 = [ 1;2;3]
A series of elements all of same type Equivalent to System.Collections.Generic.IEnumerable Sequence expressions evaluate to sequences A lot of helper functions to choose from ( map, filter, iter ) same as for lists let seq1 = seq {1..10}
A way of grouping different values and types Used to represent tree structures Data is not fixed Each possible option has a case identifier type Tree = | Nil | Node of int * Tree * Tree
An option wraps a value indicating whether it exists or not They are a simple example of discriminated union // a: int option let a = Some (42) // b: 'a option let b = None
Simple way of grouping named values We can use record expressions to set values Easy cloning with copy and update record expressions
Offers branching of the control based on comparison of an expression with a set of patterns One of the most powerful features of F# Not a simple switch statement Haskell, ML and OCaml also have it
When guards to add extra condition to the pattern // Match expression match test-expression with | pattern1 [ when condition ] -> result- expression1 | pattern2 [ when condition ] -> result- expression2 |...
NameExample Constant pattern1.0,"test",30,Color.Red Identifier patternSome(x) Failure(msg) Variable patternA as pattern(a, b) as tuple1 OR pattern([h] | [h; _]) AND pattern(a, b) & (_, "test") Cons patternh :: t List pattern[ a; b; c ] Array pattern[| a; b; c |]
NameExample Parenthesized pattern( a ) Tuple pattern( a, b ) Record pattern{ Name = name; } Wildcard pattern_ Pattern together with type annotationa : int Type test pattern:? System.DateTime as dt Null patternnull
let rec f = function | x when x failwith "Negative values are not allowed." | 0 | 1 as x -> x | x -> f (x-1) + f (x-2)
Pattern matching of Algebraic Data Types (ADTs) Allow to define named partitions for input data Partial active patterns when we need to partition only part of the input Parameterized active patterns when we have more than one argument
Use mutable to make a variable mutable let mutable a = 1 a <- 2 Arrays are mutable let array = [|1..10|] array.[2] <- 5
ref operator allows to box mutable values inside reference cells type Ref = { mutable contents: 'a } byref keyword to ask for a reference cell or the address of a typical variable
type [access-modifier] type-name [type-params]( parameter-list ) [ as identifier ] = [ class ] [inherit base-type-name(base-constructor-args) ] [ let-bindings ] [ do-bindings ] member-list Let bindings define fields or function values local to the class Do bindings define code to be executed upon creation Identifier gives a name to the instance variable
new(argument-list) = constructor-body new allows to define other constructors
// Interface declaration type interface-name = [ interface ] abstract member1 : [ argument-types1 -> ] return-type1 abstract member2 : [ argument-types2 -> ] return-type2... // Implementing, inside a class type definition: interface interface-name with member self-identifier.member1 argument-list = method-body1 member self-identifier.member2 argument-list = method-body2 // Implementing, by using an object expression let class-name (argument-list) = { new interface-name with member self-identifier.member1 argument-list = method-body1 member self-identifier.member2 argument-list = method-body2 [ base-interface-definitions ] } member-list
// Abstract class syntax. type [ accessibility-modifier ] abstract-class-name = [ inherit base-class-or-interface-name ] [ abstract-member-declarations-and-member-definitions ] // Abstract member syntax. abstract member member-name : type-signature
Virtual methods abstract member method-name : type default self-identifier.method-name argument- list = method-body override self-identifier.method-name argument- list = method-body Use object expressions as an alternative
Values, methods, properties, classes, records, discriminated unions Implicit generic constraint via type inference Explicit generic constraint
Expert F# by Don Syme Programming F# by Chris Smith CTO Corner - HubFS Matthew Podwysocki Don Syme Chris Smith