val add1 : x:int -> int

Full name: index.add1
val x : int
val number : int

Full name: index.number
val surname : string

Full name: index.surname
val add : x:int -> y:int -> int

Full name: index.add
val y : int
val sum : (int -> int -> int)

Full name: index.sum
val add' : x:int -> y:int -> int

Full name: index.add'
val three : int

Full name: index.three
val three' : int

Full name: index.three'
val add10 : (int -> int)

Full name: index.add10
val getOblgation : connectionString:'a -> obligationId:'b -> 'c

Full name: index.getOblgation
val connectionString : 'a
val obligationId : 'b
val getObligationIoC : (obj -> obj)

Full name: index.getObligationIoC
val x : 'a
val f : ('a -> 'b)
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member GetSlice : startIndex:int option * endIndex:int option -> 'T list
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val filter : predicate:('T -> bool) -> list:'T list -> 'T list

Full name: Microsoft.FSharp.Collections.List.filter
val i : int
val sum : list:'T list -> 'T (requires member ( + ) and member get_Zero)

Full name: Microsoft.FSharp.Collections.List.sum
val Log : level:string -> message:string -> string

Full name: index.Log
val level : string
val message : string
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val g : ('b -> 'c)
val mul : x:int -> y:int -> int

Full name: index.mul
val add5AndMultiplyBy3 : (int -> int)

Full name: index.add5AndMultiplyBy3
val nothing : unit

Full name: index.nothing
val doNothing : unit -> unit

Full name: index.doNothing
val collection : int []

Full name: index.collection
val collection2 : int []

Full name: index.collection2
val collection3 : int []

Full name: index.collection3
val third : int

Full name: index.third
val subCollection : int []

Full name: index.subCollection
val collection : int list

Full name: index.collection
val collection2 : int list

Full name: index.collection2
val collection3 : int list

Full name: index.collection3
val subCollection : int list

Full name: index.subCollection
val collection4 : int list

Full name: index.collection4
val collection5 : int list

Full name: index.collection5
val sequence : seq<int>

Full name: index.sequence
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val sequence2 : seq<int>

Full name: index.sequence2
val map : mapping:('T -> 'U) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
val rev : list:'T list -> 'T list

Full name: Microsoft.FSharp.Collections.List.rev
type ClientId = System.Guid

Full name: index.ClientId
namespace System
Multiple items
type Guid =
  struct
    new : b:byte[] -> Guid + 4 overloads
    member CompareTo : value:obj -> int + 1 overload
    member Equals : o:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member ToByteArray : unit -> byte[]
    member ToString : unit -> string + 2 overloads
    static val Empty : Guid
    static member NewGuid : unit -> Guid
    static member Parse : input:string -> Guid
    static member ParseExact : input:string * format:string -> Guid
    ...
  end

Full name: System.Guid

--------------------
System.Guid()
System.Guid(b: byte []) : unit
System.Guid(g: string) : unit
System.Guid(a: int, b: int16, c: int16, d: byte []) : unit
System.Guid(a: uint32, b: uint16, c: uint16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : unit
System.Guid(a: int, b: int16, c: int16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : unit
type DocumentNumber = int

Full name: index.DocumentNumber
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
type DocumentData = string

Full name: index.DocumentData
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type DocumentTuple = DocumentNumber * DocumentData

Full name: index.DocumentTuple
type QueryFunction = ClientId -> DocumentTuple list

Full name: index.QueryFunction
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
val printDocuments : query:QueryFunction -> clientId:ClientId -> unit

Full name: index.printDocuments
val query : QueryFunction
val clientId : ClientId
val iter : action:('T -> unit) -> list:'T list -> unit

Full name: Microsoft.FSharp.Collections.List.iter
val doc : DocumentTuple
val printf : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf
val intANDstring : int * string

Full name: index.intANDstring
val t2 : bool * string

Full name: index.t2
val t3 : int * string * bool

Full name: index.t3
val n1 : bool

Full name: index.n1
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val n2 : string

Full name: index.n2
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val b : bool

Full name: index.b
val str : string

Full name: index.str
type DocumentRecord =
  {Number: DocumentNumber;
   Data: DocumentData;
   IsSigned: bool;}

Full name: index.DocumentRecord
DocumentRecord.Number: DocumentNumber
Multiple items
DocumentRecord.Data: DocumentData

--------------------
namespace Microsoft.FSharp.Data
DocumentRecord.IsSigned: bool
type bool = System.Boolean

Full name: Microsoft.FSharp.Core.bool
val document : DocumentRecord

Full name: index.document
namespace Microsoft.FSharp.Data
val signDocument : doc:DocumentRecord -> DocumentRecord

Full name: index.signDocument
val doc : DocumentRecord
val d : DocumentData

Full name: index.d
type intORstring =
  | Int of int
  | String of string

Full name: index.intORstring
union case intORstring.Int: int -> intORstring
Multiple items
union case intORstring.String: string -> intORstring

--------------------
module String

from Microsoft.FSharp.Core
type Shape =
  | Circle of Radius: float
  | Triangle of Base: float * Height: float
  | Rectangle of Length: float * Height: float

Full name: index.Shape
union case Shape.Circle: Radius: float -> Shape
Multiple items
val float : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------
type float = System.Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
union case Shape.Triangle: Base: float * Height: float -> Shape
union case Shape.Rectangle: Length: float * Height: float -> Shape
type DocumentRecord' =
  {Number: DocumentNumber;
   Data: DocumentData;}

Full name: index.DocumentRecord'
DocumentRecord'.Number: DocumentNumber
Multiple items
DocumentRecord'.Data: DocumentData

--------------------
namespace Microsoft.FSharp.Data
type DocumentUnion =
  | Unsigned of DocumentRecord'
  | Signed of DocumentRecord'

Full name: index.DocumentUnion
union case DocumentUnion.Unsigned: DocumentRecord' -> DocumentUnion
union case DocumentUnion.Signed: DocumentRecord' -> DocumentUnion
val signDocument : document:DocumentUnion -> DocumentUnion

Full name: index.signDocument
val document : DocumentUnion
val doc : DocumentRecord'
Multiple items
union case SignedDocument.SignedDocument: DocumentRecord' -> SignedDocument

--------------------
type SignedDocument = | SignedDocument of DocumentRecord'

Full name: index.SignedDocument
Multiple items
union case UnsignedDocument.UnsignedDocument: DocumentRecord' -> UnsignedDocument

--------------------
type UnsignedDocument = | UnsignedDocument of DocumentRecord'

Full name: index.UnsignedDocument
val signDocument2 : UnsignedDocument -> SignedDocument

Full name: index.signDocument2
val record : DocumentRecord'
val printValue : optionalInt:string option -> string

Full name: index.printValue
val optionalInt : string option
union case Option.Some: Value: 'T -> Option<'T>
val i : string
union case Option.None: Option<'T>
val posNeg : number:int -> string

Full name: index.posNeg
val number : int
val n : int
val describe : list:'a list -> string

Full name: index.describe
Multiple items
val list : 'a list

--------------------
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
val a : 'a
val sum : list:int list -> int

Full name: index.sum
Multiple items
val list : int list

--------------------
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
val head : int
val tail : int list
type Person =
  {First: string;
   Last: string;}

Full name: index.Person
Person.First: string
Person.Last: string
val matchJohn : person:Person -> string

Full name: index.matchJohn
val person : Person
Multiple items
type Customer =
  new : unit -> Customer
  new : firstName:string * lastName:string -> Customer
  member GetFullName : unit -> string
  member FirstName : string
  member LastName : string

Full name: index.Customer

--------------------
new : unit -> Customer
new : firstName:string * lastName:string -> Customer
val firstName : string
val lastName : string
val this : Customer
member Customer.FirstName : string

Full name: index.Customer.FirstName
member Customer.LastName : string

Full name: index.Customer.LastName
member Customer.GetFullName : unit -> string

Full name: index.Customer.GetFullName
property Customer.FirstName: string
property Customer.LastName: string
val customer : Customer

Full name: index.customer
val fullName : string

Full name: index.fullName
member Customer.GetFullName : unit -> string
Multiple items
type CustomerMutable =
  new : firstName:obj * lastName:obj -> CustomerMutable
  member FirstName : obj
  member LastName : obj
  member LastName : obj with set

Full name: index.CustomerMutable

--------------------
new : firstName:obj * lastName:obj -> CustomerMutable
val firstName : obj
val lastName : obj
val this : CustomerMutable
member CustomerMutable.FirstName : obj

Full name: index.CustomerMutable.FirstName
val mutable _firstName : obj
val set : elements:seq<'T> -> Set<'T> (requires comparison)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.set
member CustomerMutable.LastName : obj with set

Full name: index.CustomerMutable.LastName
val mutable _lastName : obj
val value : obj
type ICalculator =
  interface
    abstract member Add : int -> int -> int
    abstract member Substract : int -> int -> int
    abstract member CurrentValue : int
    abstract member Pi : float
    abstract member CurrentValue : int with set
  end

Full name: index.ICalculator
abstract member ICalculator.Add : int -> int -> int

Full name: index.ICalculator.Add
abstract member ICalculator.Substract : int -> int -> int

Full name: index.ICalculator.Substract
abstract member ICalculator.Pi : float

Full name: index.ICalculator.Pi
abstract member ICalculator.CurrentValue : int with set

Full name: index.ICalculator.CurrentValue
Multiple items
type Calculator =
  interface ICalculator
  new : unit -> Calculator

Full name: index.Calculator

--------------------
new : unit -> Calculator
val this : Calculator
override Calculator.Add : x:int -> y:int -> int

Full name: index.Calculator.Add
override Calculator.Substract : x:int -> y:int -> int

Full name: index.Calculator.Substract
override Calculator.Pi : float

Full name: index.Calculator.Pi
override Calculator.CurrentValue : int with set

Full name: index.Calculator.CurrentValue
val mutable _currentValue : int
val value : int
val calc : Calculator

Full name: index.calc
val result : obj

Full name: index.result
val calc : ICalculator

Full name: index.calc
val this : ICalculator
abstract member ICalculator.Add : int -> int -> int
abstract member ICalculator.Substract : int -> int -> int
property ICalculator.Pi: float
property ICalculator.CurrentValue: int
Multiple items
type MeasureAttribute =
  inherit Attribute
  new : unit -> MeasureAttribute

Full name: Microsoft.FSharp.Core.MeasureAttribute

--------------------
new : unit -> MeasureAttribute
[<Measure>]
type degC

Full name: index.degC
[<Measure>]
type degF

Full name: index.degF
val convertCtoF : temp:float<degC> -> float<degF>

Full name: index.convertCtoF
val temp : float<degC>
val convertFtoC : temp:float<degF> -> float<degC>

Full name: index.convertFtoC
val temp : float<degF>
val testNum : n:int -> unit

Full name: index.testNum
active recognizer Even: int -> Choice<unit,unit>

Full name: index.( |Even|Odd| )
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
active recognizer Odd: int -> Choice<unit,unit>

Full name: index.( |Even|Odd| )
namespace System.Text
namespace System.Text.RegularExpressions
val pattern : string
val input : string
val matches : MatchCollection
Multiple items
type Regex =
  new : pattern:string -> Regex + 1 overload
  member GetGroupNames : unit -> string[]
  member GetGroupNumbers : unit -> int[]
  member GroupNameFromNumber : i:int -> string
  member GroupNumberFromName : name:string -> int
  member IsMatch : input:string -> bool + 1 overload
  member Match : input:string -> Match + 2 overloads
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  member Replace : input:string * replacement:string -> string + 5 overloads
  ...

Full name: System.Text.RegularExpressions.Regex

--------------------
Regex(pattern: string) : unit
Regex(pattern: string, options: RegexOptions) : unit
Regex.Matches(input: string, pattern: string) : MatchCollection
Regex.Matches(input: string, pattern: string, options: RegexOptions) : MatchCollection
property MatchCollection.Count: int
val m : Match
property Capture.Value: string
val testString : _arg1:string -> unit

Full name: index.testString
active recognizer RegexContains: string -> string -> string list option

Full name: index.( |RegexContains|_| )
val urls : string list
val emails : string list
val numbers : string list
namespace Microsoft.FSharp
Multiple items
type LiteralAttribute =
  inherit Attribute
  new : unit -> LiteralAttribute

Full name: Microsoft.FSharp.Core.LiteralAttribute

--------------------
new : unit -> LiteralAttribute
val sample : string

Full name: index.sample
type BookTypes = obj

Full name: index.BookTypes
val author : obj

Full name: index.author
val book : obj

Full name: index.book
Multiple items
type OptionBuilder =
  new : unit -> OptionBuilder
  member Bind : v:'d option * f:('d -> 'e option) -> 'e option
  member Return : v:'c -> 'c option
  member ReturnFrom : o:'b -> 'b
  member Zero : unit -> 'a option

Full name: index.OptionBuilder

--------------------
new : unit -> OptionBuilder
val x : OptionBuilder
member OptionBuilder.Bind : v:'d option * f:('d -> 'e option) -> 'e option

Full name: index.OptionBuilder.Bind
val v : 'd option
val f : ('d -> 'e option)
module Option

from Microsoft.FSharp.Core
val bind : binder:('T -> 'U option) -> option:'T option -> 'U option

Full name: Microsoft.FSharp.Core.Option.bind
member OptionBuilder.Return : v:'c -> 'c option

Full name: index.OptionBuilder.Return
val v : 'c
member OptionBuilder.ReturnFrom : o:'b -> 'b

Full name: index.OptionBuilder.ReturnFrom
val o : 'b
member OptionBuilder.Zero : unit -> 'a option

Full name: index.OptionBuilder.Zero
val opt : OptionBuilder

Full name: index.opt
val someValue : int option

Full name: index.someValue
val noneValue : int option

Full name: index.noneValue

Czego się dzisiaj dowiemy

  • Funkcje to nie metody
  • Typy to nie klasy
  • Kompozycja to nie dziedziczenie
  • F# jest całkiem zacny

Funkcje matematyczne

\(f:A \rightarrow B\)

  • A - dziedzina, czyli zbiór argumentów funkcji
  • B - przeciwdziedzina, czyli zbiór wartości funkcji

Funkcje matematyczne

\(f(x) = x + 1\)

Funkcja

1: 
let add1 x = x + 1

Cechy funkcji

  • zawsze zwraca tą samą wartość dla tego samego argumentu (jest mapą wartości)
  • nie może mieć skuktów ubocznych (czystość)
  • argumenty oraz wartości funkcji są niezmienne
  • ma zawsze jedno wejście i jedno wyjście

Co nam to daje?

  • Bardzo uproszczona aplikacja paraleizmu. Locki, mutexy i inne podobne są zbędne.
  • Lazy evaluation na pierwszym miejscu
  • Kolejność wywołania funkcji nie ma (aż tak dużego) znaczenia
  • Każda funkcja może być cache'owalna (memoization)

Krótko o F#

wieloparadygmatowy język programowania zawierający w sobie głównie cechy języka funkcyjnego, ale umożliwiającym także pisanie kodu imperatywnego oraz obiektowego. Jest językiem silnie typowanym zaprojektowanym w celu pisania prostego, solidnego i wydajnego kodu do rozwiązywania złożonych problemów. Jest uruchamiany na platformie .NET.

Zasady F#

  • Domyślnie immutable
  • Wszystko jest wyrażeniem (expression), które zwraca wynik
  • Funkcje zawsze przyjmują parametry wejściowe i zwracają wynik
  • Formatowanie jest ważne
  • Kolejność plików jest ważna, aby zapobiec cyklicznym zależnościom

Możliwości F#

  • Zaawansowane wnioskowanie typów (type inference)
  • Pattern matching + Active Patterns
  • Discriminated unions
  • Computation Expressions
  • Async Workflows + MailboxProcessor (actor pattern)

Expression vs statement

  • Celem expression jest zawsze stworzenie wartości (plus ewentualne skutki uboczne)
  • Celem statement są zawsze skutki uboczne
1: 
2: 
3: 
4: 
5: 
6: 
// statement
int result;
if(retryCount > 5)
{
    result = -1;
}

vs

1: 
2: 
//expression
int result = retryCount > 5 ? -1 : 0;

programowanie imperatywne

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
// statement
var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evenNumbers = new List<int>();
foreach (var number in numbers)
{    
    if (number % 2 == 0)
    {
        evenNumbers.Add(number);
    }
}

vs

1: 
2: 
// expression
var evenNumbers = numbers.Select(number => number % 2 == 0);

programowanie deklaratywne

Podstawy F#

Wartości

1: 
2: 
let number = 5
let surname = "Kowalski"

Funkcje

1: 
2: 
let add x y = x + y
let sum = add

Currying

1: 
2: 
3: 
let add x y = x + y

let add' x = fun y -> x + y

Currying

1: 
2: 
3: 
4: 
let add x y = (+) x y

let three = ((add 1) 2)
let three' = (((+) 1) 2)

Partial application

1: 
2: 
3: 
let add x y = (+) x y

let add10 = (+) 10

Partial application

1: 
2: 
3: 
let getOblgation connectionString obligationId = ...

let getObligationIoC = getOblgation @"Server=.;Database=db;Trusted_Connection=True;"

Coś to przypomina?

Pipe

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let (|>) x f = f x

[1..4]
|> List.filter (fun i -> i > 2)
|> List.sum

let Log level message = sprintf "[%s] - %s" level message
"some warning" |> Log "Warn"

Kompozycja

1: 
2: 
3: 
4: 
5: 
6: 
let (>>) f g x = g (f x)

let add x y = x + y
let mul x y = x * y

let add5AndMultiplyBy3 = add 5 >> mul 3

Typ unit

Podobny do void, ale jest typem, a nie słowem kluczowym

1: 
2: 
3: 
let nothing = ()

let doNothing () = ()

Kolekcje

Tablica

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
let collection = [| 1; 2; 3; 4; 5 |]

let collection2 = [| 1 .. 5 |]

let collection3 = [| for i in 1 .. 10 -> i * i  |]

let third = collection.[2]

let subCollection = collection.[2..]

Lista

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
let collection = [ 1; 2; 3; 4; 5 ]

let collection2 = [ 1 .. 5 ]

let collection3 = [ for i in 1 .. 10 -> i * i  ]

let third = collection.[2]

let subCollection = collection.[2..]
1: 
2: 
3: 
let collection4 = collection @ collection2

let collection5 = 125 :: collection

Sekwencja

Seq<'T> to po prostu IEnumerable<T>

1: 
2: 
3: 
let sequence = seq { 1 .. 5 }

let sequence2 = seq { for i in 1 .. 10 -> i * i  }

Użycie

1: 
2: 
3: 
4: 
[1 .. 20 .. 1000]
|> List.map (fun i -> i * 2)        // select
|> List.filter (fun i -> i > 20)    // where
|> List.rev                         // reverse

Typy algebraiczne

Aliasy

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
type ClientId = System.Guid
type DocumentNumber = int
type DocumentData = string
type DocumentTuple = DocumentNumber * DocumentData

type QueryFunction = ClientId -> DocumentTuple list

let printDocuments (query:QueryFunction) (clientId:ClientId) = 
    clientId |> query |> List.iter (fun doc -> printf "%A" doc)

Tuple

Tuple

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let intANDstring = (1, "str")

let t2 = (true, "data")
let t3 = (1, "data", false)

let n1 = fst t2
let n2 = snd t2
let (b, str) = t2

Rekordy

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
type DocumentRecord = 
    { Number: DocumentNumber 
      Data: DocumentData 
      IsSigned: bool }

let document = { Number = 1; Data = "data"; IsSigned = false }

let signDocument doc = { doc with IsSigned = true }

let { Data = d; IsSigned = b } = signDocument document

Unie

Tuple

1: 
type intORstring = | Int of int | String of string

Unie

1: 
2: 
3: 
4: 
type Shape =
| Circle of Radius : float
| Triangle of Base : float * Height : float
| Rectangle of Length : float * Height : float

Unie

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
type DocumentRecord' = { Number: DocumentNumber; Data: DocumentData; } 

type DocumentUnion = 
| Unsigned of DocumentRecord'
| Signed of DocumentRecord'

let signDocument (document: DocumentUnion) =
    match document with
    | Signed _ -> document
    | Unsigned doc -> Signed doc

Pojedyńcze unie

1: 
2: 
3: 
4: 
5: 
type SignedDocument = SignedDocument of DocumentRecord'

type UnsignedDocument = UnsignedDocument of DocumentRecord'

let signDocument2 (UnsignedDocument record) = SignedDocument record

Pattern matching

Match po typie

1: 
2: 
3: 
4: 
let printValue optionalInt = 
    match optionalInt with 
    | Some i -> sprintf "Have value %s!" i
    | None -> sprintf "No value"

Match warunkowy

1: 
2: 
3: 
4: 
5: 
let posNeg number =
    match number with
    | n when n > 0 -> "positive"
    | n when n < 0 -> "negative"
    | _ -> "zero"

Match po elementach kolekcji

1: 
2: 
3: 
4: 
5: 
6: 
let describe list =
    match list with
    | [] -> "empty"
    | [a] -> sprintf "only %A" a
    | [a; _] -> sprintf "two elements beginning with %A" a
    | _ -> "lots of elements"

Match używany w funkcji rekurencyjnej

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

Match wartości pola rekordu

1: 
2: 
3: 
4: 
5: 
6: 
type Person = { First:string; Last:string }

let matchJohn person = 
    match person with 
    | {First="john"}  -> sprintf "Matched John" 
    | _  -> sprintf "Not John" 

Programowanie obiektowe

Klasy

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
type Customer(firstName, lastName) = 

    // default constructor
    new () =
        Customer("john", "doe")

    member this.FirstName = firstName
    member this.LastName = lastName

    member this.GetFullName() = 
        sprintf "%s %s" this.FirstName this.LastName

let customer = new Customer("John", "Doe")
let fullName = customer.GetFullName()
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
type CustomerMutable(firstName, lastName) =

    let mutable _firstName = firstName
    let mutable _lastName = lastBame

    member this.FirstName 
        with get() = _firstName
        with set(value) = _firstName <- value

    member this.LastName
        with get() = _lastName
        and set(value) = _lastName <- value

Interfejsy

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
type ICalculator =
    abstract member Add: int -> int -> int
    abstract member Substract: int -> int -> int

    // immutable property
    abstract member Pi : float 

    // read write property
    abstract member CurrentValue : int with get,set
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
type Calculator() = 
    
    let mutable _currentValue = 0

    interface ICalculator with
        member this.Add x y = x + y
        member this.Substract x y = x - y
        
        member this.Pi = 3.14

        member this.CurrentValue
            with get() = _currentValue
            and set(value) = _currentValue <- value

let calc = new Calculator()
let result = calc.Add 1 2

Object expressions

1: 
2: 
3: 
4: 
5: 
6: 
let calc = 
    { new ICalculator with 
      member this.Add x y = x + y
      member this.Substract x y = x + y
      member this.Pi = 3.14
      member this.CurrentValue with get() = 0 and set(value) = () }

Inne ciekawostki języka

Units of measure (jednostki miary)

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
[<Measure>]
type degC

[<Measure>]
type degF

let convertCtoF (temp: float<degC>) = 
    9.0<degF> / 5.0<degC> * temp + 32.0<degF>

let convertFtoC (temp: float<degF>) = 
    5.0<degC> / 9.0<degF> * (temp - 32.0<degF>)

Active patterns

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let (|Even|Odd|) n =
    if n % 2 = 0 then Even
    else Odd
    
let testNum n =
    match n with
    | Even -> printfn "%i is even" n
    | Odd -> printfn "%i is odd" n

Partial Active patterns

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
open System.Text.RegularExpressions

let (|RegexContains|_|) pattern input = 
    let matches = Regex.Matches(input, pattern)
    if matches.Count > 0 
    then Some [ for m in matches -> m.Value ]
    else None

let testString = function
    | RegexContains "http://\S+" urls -> printfn "Urls: %A" urls
    | RegexContains "[^@]@[^.]+\.\W+" emails -> printfn "Emails: %A" emails
    | RegexContains "\d+" numbers -> printfn "Numbers: %A" numbers
    | _ -> printfn "Didn't find anything."

Type providers

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
open FSharp.Data

[<Literal>]
let sample = @"{
    ""title"" : ""Management 4.2"",
    ""author"" : {
        ""firstName"" : ""Jurgen"",
        ""lastName"" : ""Appelo""
    },
    ""ISBN"" : ""978-0321123479""
}"

type BookTypes = JsonProvider<sample, RootName="book">

let author = BookTypes.Author("Philip K.", "Dick")
let book = BookTypes.Book("Ubik", author, "isbn")

Computation Expressions

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
type OptionBuilder() =
    member x.Bind(v,f) = Option.bind f v
    member x.Return v = Some v
    member x.ReturnFrom o = o
    member x.Zero () = None
let opt = OptionBuilder()

let someValue =
    opt {
        let x = 12
        let! y = Some 11
        return x + y
    }

let noneValue =
    opt {
        let x = 12
        let! y = None
        return x + y
    }

Linki

http://fsharpforfunandprofit.com/