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

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

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

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