The Greater Helsinki Area F# User Group - F# & Azure - FI EN

F# in Brief

F# is a clear programming language, which, by default, drives user towards functional programming solutions. This way the program state modelling goes correctly and programs are easily multi-threaded and they have good maintainability.

"Functional programming combines the flexibility and power of abstract mathematics with the intuitive clarity of abstract mathematics." - XKCD

Although small is beautiful, and F# can be very abstract language, it is not about to get the most succinct syntax. It is about the best (and most clear) syntax fitting for the situation. The power of a language is to be able to do things in many ways, but goodness to intuitively drive the user to the best solution.

Maybe a small step from experimental trial-and-error-program-maintenance to a bit more mathematical way wouldn't be so bad?

You may learn to read the code easily, but painless writing of the programs will take its time: learning new things will take some patience. F#-compiler is stricter than C# compiler, so you have to hit your head to the wall at first, but when the code compiles, it will more probably not fail runtime. On the other hand it will give some achievement-feeling and make C#-veteran to feel that coding can be fun.

Creating F-Sharp-project in the Visual Studio

You can either use Azure-Worker-role (which has separate instructions), or make a new project. By default F# project will compile as dll, like C#-project, and those are compatible which each other.

If you want to make a new project in Visual Studio: File -> New -> Project... -> Other Languages -> Visual F# ->F# Library

C# with F# (and why not also VB.NET)

The strengths of C# is the ready-made wizards when they are enough, like in XAML-development. From F# you may reference and use C#-dlls directly. The same Visual Studio solution may have both F# and C# projects, but the visibility of the changes needs a compilation of the referenced project.

Try to add C#-project (library, console-app, test project, or something) to the same solution with F# project and add a reference: From Solution Explorer, C#-project, References-folder: right click and: Add reference... -> Solution -> check mark F#-project and OK.

Here is a sample content for F#-file (with more details below):

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
namespace MyLibrary

type MyClass1() = 
    member this.X = "F#"

module MyModule =

    let StaticItems = 42

    let MyList = ["a";"b";"c"] |> List.toSeq

    let MyAddFive x = x+5;

    let MyGenericFunction x = "Hello " + x.ToString();

    type UserData1() = 
        member val Email = "" with get, set

...and those can be used (after compilation) from the C#-project's class directly:

var class1 = new MyLibrary.MyClass1();
var fromFs = class1.X;

int Item = MyLibrary.MyModule.StaticItems;

IEnumerable<string> response = MyLibrary.MyModule.MyList;

int seven = MyLibrary.MyModule.MyAddFive(2);

var res = MyLibrary.MyModule.MyGenericFunction<int>(2);

var class2 = new MyLibrary.MyModule.UserData1();
class2.Email = "no@spam.com";

This will be a safety net for old C#-developer before F# is totally under belt. Likewise would work referencing to VB.NET-component.

Notable limitations:

  • Property/variable/function names are usually written in lower case in F#.
    • But this is only a practice to separate those from types/classes.
  • F#-default-list is a linked list of F#-core.
    • Seq is a strongly typed IEnumerable.
  • Also F#-default-function is a function of F#-core.
    • From F# you may call C#-method that takes C# Func-parameter, F#-function is OK in this way.
    • But if you return a function from F#, then the C# developer will get confused.
    • You may explicitly return C# Func -data type from F#, but using C# Func inside F# is not natural.
      • Func and Action are separate classes in C#, and "void" is not a type.
      • F# void is called unit and it is a data type.

These limitations will matter, if you know in the first place, that you will develop F#-component to use from C#-development.

Then the language itself:

Hello world

With .NET classes, "Hello World"-program can be created e.g. this way:

1: 
2: 
3: 
open System
let x = "Hello World"
Console.WriteLine x

F# will drive you to the direction that you don't re-use your "variables" (/values) by default. So that when x is once defined, rather use x2 next time (...with better naming conventions). Actually you need variables only to maintain mutable state of loops. F# will drive you to use recursion instead of loops by default. More about this later...

When comparing equality, just one equals sign is used. Comments are // or ( and ). Private and public scopes are in use.

You may also give values long names with spaces like these (but international keyboard layouts will make these a bit more difficult to use):

1: 
let ``Hello World Container`` = "Hello World"

Interactive

Assuming that Resharper has not totally messed-up your keyboard short-cuts:

Press Ctrl+Alt+F to get the interactive-window ("REPL-loop"), where you may execute code on-the-fly. You may write code directly to this window and execute it by writing two semicolons before the last enter-key, for example:

1: 
let z = 4;;

Or you can also select multiple lines of code from your F#-file and then send it to the interactive-window (from right mouse click menu, "Execute in interactive", or) with keyboard short-cut Alt+Enter

Usually the best practice is to define initial values for parameters and then send the wanted code-block to interactive.

There are some good unit testing and BDD -frameworks that can be used with F#. But interactive is better for experimental-development so these frameworks are mostly needed to ensure maintainability.

Type system

Type system is for compiler to serve the developer, not for developer to serve the compiler. F# will do a good job to resolve types by itself, but sometimes the developer wants to define types manually:

1: 
2: 
3: 
let f1 x = x+4.5m 
let f2 (x:decimal) = x+4.5m //argument type
let f3 x :decimal = x+4.5m  //function type

Generic types (the classic T, T1, T2, ...) have the type syntax of: 'a, 'b, 'c, ...

Pipes

F# has operation "|>", which moves the last parameter of a method to first:

1: 
2: 
open System
"Hello World" |> Console.WriteLine

This can be thought a bit like C# extension methods: if functions are verbs, it is usually more natural to start a sentence with substantive, the language is more natural:

"a dog barks to a human" versus "barks(a dog, to a human)"

Functions

You don't need brackets in function parameters, and comma is reserved for Tuple-class, so you may define a function with parameters like this:

1: 
let f x y = x+y

The function type syntax is like C#-language Func<...>-class parameters, e.g.: Func is a function that takes input two numbers and returns a string. In F#, there is an arrow between parameters, so the corresponding function type syntax is

1: 
int -> int -> string

You can often figure out what the function does just by the function type syntax.

Parameter-less function are defined with brackets. You need this when you don't want to execute evaluation immediately. "return"-statement is not usually needed, because the function will return the value of the last call anyway. Functions can locate inside of other functions.

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let sayHello () = 
    let hello = 
        let ello = "ello"
        "h"+ello
    let world = 
        "world"
    hello + " " + world

Lambda-function is constructed by the fun-keyword and arrow.

Lists

F# has even more diverse list-manipulation-libraries than the LINQ-library, but you may also use the LINQ-library if you already know that well.

There appears to be three different types of lists widely used, which have mostly the same operations in the libraries. Exaggerate by generalizing, it goes like this:

  • List
    • Best maintainability in the code.
    • Immutable: items won't change
    • Two colon signs may be used to match/separate the first item and a list of the rest.
    • At-sign "@" may be used to concatenate/merge two lists.
  • Array
    • Best efficiency. Corresponds the C#-array.
    • By default, it is an anti-pattern to point directly at the index. It can be done by writing period-sign before square brackets.
  • Seq
    • Best compatibility. This corresponds the C# IEnumerable.

Lists can be converted to other forms: List.toArray, List.toSeq, Seq.toList, Array.toSeq, ... Some code examples:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
let emptyList = []

let listOfLists = [[1;2;3];[4;5;6]]

let myList = 
    [1..10] |> List.filter(fun i -> i%2=0)
let mySeq =
    [|1..10|] |> Seq.filter(fun i -> i%2=0)

let merged = [1;2;3] @ [4;5;6]

let head::tail = ["h";"t1";"t2";"t3"]

let ``A and H to Z`` = 'A'::['H'..'Z']

open System.Linq
let threeFirst = 
    mySeq.Take(3)
    |> Seq.toArray
    |> Array.map(fun i -> i*3)

You can compose function with ">>" -operator. "First do this then this."

1: 
2: 
3: 
let composed = 
    List.filter(fun i -> i%2=0) >> List.map(fun i -> i+5)
[6; 5; 3; 2; 4] |> composed

Manual typing can be done either C#-way or OCaml-way:

1: 
2: 
let emptyList2:list<bigint> = []
let emptyList3:bigint list = []

Tuple

Besides lists, other common structure is a Tuple: List is n-times one same type of items, tuple is one item of each n separate types. C# also have the Tuple-class and this is the same class.

You could create tuple like C#-way System.Tuple.Create(1, "a", 1.0), but there is a lot easier way, just plain comma-sign. Tuple may be dissembled to pieces, either with fst- and snd-operations, or by defining "temp-variables" in the left side of equality-operator:

1: 
2: 
let tuple = 1, "a", 1.0
let a, b, c = tuple

Tuple is marked as times-sign "" in the type syntax, like: intstring.

Classes

F# is also a great Object-Oriented-language.

Object having one property, email, which has a getter and a setter, and the default value for that is an empty string, would be implemented like this:

1: 
2: 
3: 
4: 
type UserData1() = 
   member val Email = "" with get, set

let myInstance1 = UserData1()

When you create a new instance of an object, the new-keyword is optional.

Object, having constructor with parameter of a readonly-property, email, and also empty constructor (setting empty string as default), would be implemented like this:

1: 
2: 
3: 
type UserData2(email) =
   new() = UserData2("")
   member x.Email = email

Inheritance-syntax is not as handy as in C#, because the type checking needs explicit implementation of interfaces:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
type Base() =
    let DoSomething() = ()
    abstract member Method : unit -> unit
    default x.Method() = DoSomething()

type ``My inherited class with dispose``() =
    inherit Base()
    override x.Method() =
        base.Method()

    interface IDisposable with
        override x.Dispose() = 
            //Dispose resources...
            GC.SuppressFinalize(x)

Discriminated union

You can construct "either-or"-types:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
type myEnum =
| A
| B

type CalendarEvent =
| ExactTime of DateTime
| MonthAndYear of string*int //month*year

type Tree =
| Leaf of int
| Node of Tree*Tree

One usage of this is the program state management, in compile-time, avoiding the runtime if-logic-jungle. Discriminated unions are very handy with pattern matching.

Some more particular types

Type can be only alias, or "either-or" can have only one case:

1: 
2: 
3: 
type aliasItem<'a,'b> = System.Collections.Generic.KeyValuePair<'a,'b>

type OrderId = | Id of System.Guid

Type may be a record:

1: 
2: 
3: 
4: 
5: 
6: 
type Address = { 
    Street: string; 
    Zip: int; 
    City: string; 
}
let myAddrr = { Street = "Juvank."; Zip = 33710; City = "Tre"; }

...or it could define a compile-time-checking with Measure-attribute. A bit like separate class to capsulate only one value (but exposing/displaying that always), so that different things or unit of measures won't ever mix by accident:

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

[<Measure>]
type LTC

let rate =
    let ratePlain = 9.45m //fetch from internet...
    ratePlain * 1m<EUR/LTC>

let myMoneyInEur (x:decimal<LTC>) = x*rate 

let converted = myMoneyInEur 7m<LTC>

The easiest way to convert basic-.NET-type to a unit-of-measure is multiplying it by one unit. Aesthetic downside is that this will bring "greater than" and "less than" signs to the source code.

Pattern matching

Pattern-matching is a kind of switch/case or if-elseif-pattern done right, where the condition can't change on on-the-fly, but separate cases don't have the restriction of being constants. There exist several patterns.

Also, function can directly be a pattern-function or it can use so called "active patterns" to make the intention of the code more clear. Here is the same functionality in multiple ways:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
let MyFunction1 a =
   if a = "A" then 1
   elif a = "B" then 2
   else 3

let MyFunction2 a = 
   match a with
   | "A" -> 1
   | "B" -> 2
   | _ -> 3

let MyFunction3 = fun a -> 
   match a with
   | "A" -> 1
   | "B" -> 2
   | _ -> 3

let MyFunction4 = function
   | "A" -> 1
   | "B" -> 2
   | _ -> 3

let MyFunction5 a = 
   match a with
   | x when x = "A" -> 1
   | x when x = "B" -> 2
   | x -> 3


let MyFunction6 a = 

    let (|FirstVowel|FirstConsonant|Other|) p =
        match p with
        | "A" -> FirstVowel
        | "B" -> FirstConsonant
        | _ -> Other

    match a with
    | FirstVowel -> 1
    | FirstConsonant -> 2
    | Other -> 3

Usually, if possible, it is best practice to leave the default-condition away, because then the compiler will catch mistakes, if unknown conditions are added afterwards to the code.

Option type: World without Null

In C#, the NULL has two meanings: It is a "special case" (Fowler: PoEAA) and also it is un-assigned-variable. Two roles of the same construct makes things messy.

NULL is not used in F# per se. The construct to work as unknown value is option-type:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
let echo x = "You have to work " + x.ToString() + " hours."

let ``working hours`` =
    let day = (int System.DateTime.Now.DayOfWeek)
    match day with
    | 0 | 6 -> None
    | _ -> Some(7.5)

let echoHours1 = 
    match ``working hours`` with
    | None -> ""
    | Some h -> echo h

let echoHours2 = 
    ``working hours`` 
    |> Option.map(fun h -> echo h)

let echoHours3 = 
    ``working hours`` 
    |> Option.map(echo)

Recursion

Recursive function is stated as keyword rec. The best practice is to encapsulate the recursion itself inside another function, to hide "useless" initial values. One common practice is to use last parameter as "accumulator", to collect the result of the recursion. The reason is that then the compiler can optimize the stack away with the tail-recursion, so you won't get StackOverflowException even if the recursion would be deep.

1: 
2: 
3: 
4: 
5: 
6: 
let sumItems myList =
    let rec calculate li acc =
        match li with
        |[] -> acc
        |h::t -> calculate t (h+acc)
    calculate myList 0

Of course this typical function is also included in the List-library, but if you would need more complex custom-functionality, then writing explicit recursion is sometimes the right solution.

Computation Expressions

These are kind of capsules to encapsulate side-effects of some functionality. Out-of-the-box you get e.g. seq (for sequences) and async (for asynchronous code), but you can create more by yourself.

The side-effect of asynchrony is that you have to wait. Async.RunSynchronously is not very useful by itself, but Async has a lot of other possibilities also.

The main point is that when you look the code sum = x + y below, it seems very typical F#-code, even if we are in the context of the side-effect. And the side-effect itself, the async, is explicitly stated in the code. The bang (exclamation mark, "!"-sign) syntax means a call to the "computation expression"-interface.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
let asyncOperation = Async.Sleep 3000

let waitAndReturn = 
    async {
        do! asyncOperation
        return 3.0
    }

let waitAndReturn2 = 
    async {
        let! x = waitAndReturn
        let y = 7.0
        let sum = x + y
        return sum
    }

let result = Async.RunSynchronously waitAndReturn2

If you compare this to C#, the seq { ... } equivalent is LINQ. But LINQ is kind of a language its own, which is a separate learning curve for the developer. And the developer doesn't always know if (s)he is coding LINQ against IEnumerable, IQueryable, IObservable, or what... A bit naive and C#:ish but working example of seq-expression:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
open System.Linq
let slice mySeq = 
    let chunkSize = 5
    let rec seqSlice (s:int seq) =
        seq{
            yield s.Take chunkSize
            yield! seqSlice (s.Skip chunkSize)
        }
    seqSlice mySeq

"Computation Expressions" is another name to the thing aka. "Monad".

Exercises

  • Create a recursive program that lists 1000 first numbers of Fibonacci-sequence (1, 1, 2, 3, 5, 8, 13, ...).
  • Create a C# unit test or console application to call that program.

Links

If this wasn't complete enough, you might want to check this material. If you want to practise list-manipulation-libraries, you could do some Project Euler -exercises. If you want some separate code examples of one subject, then fssnip.net is a good site to begin with.

Back to the menu

Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  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 toSeq : list:'T list -> seq<'T>

Full name: Microsoft.FSharp.Collections.List.toSeq
Multiple items
type UserData1 =
  new : unit -> UserData1
  member Email : string
  member Email : string with set

Full name: FSharpBasicsEng.UserData1

--------------------
new : unit -> UserData1
val set : elements:seq<'T> -> Set<'T> (requires comparison)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.set
namespace System
Multiple items
val decimal : value:'T -> decimal (requires member op_Explicit)

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

--------------------
type decimal = System.Decimal

Full name: Microsoft.FSharp.Core.decimal

--------------------
type decimal<'Measure> = decimal

Full name: Microsoft.FSharp.Core.decimal<_>
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<_>
Multiple items
val string : value:'T -> string

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

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

Full name: Microsoft.FSharp.Core.string
val sayHello : unit -> string

Full name: FSharpBasicsEng.sayHello
val hello : string
val ello : string
val world : string
val emptyList : 'a list

Full name: FSharpBasicsEng.emptyList
val listOfLists : int list list

Full name: FSharpBasicsEng.listOfLists
val myList : int list

Full name: FSharpBasicsEng.myList
val filter : predicate:('T -> bool) -> list:'T list -> 'T list

Full name: Microsoft.FSharp.Collections.List.filter
val i : int
val mySeq : seq<int>

Full name: FSharpBasicsEng.mySeq
module Seq

from Microsoft.FSharp.Collections
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.filter
val merged : int list

Full name: FSharpBasicsEng.merged
val head : string

Full name: FSharpBasicsEng.head
val tail : string list

Full name: FSharpBasicsEng.tail
val ( A and H to Z ) : char list

Full name: FSharpBasicsEng.( A and H to Z )
namespace System.Linq
val threeFirst : int []

Full name: FSharpBasicsEng.threeFirst
(extension) System.Collections.Generic.IEnumerable.Take<'TSource>(count: int) : System.Collections.Generic.IEnumerable<'TSource>
val toArray : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Seq.toArray
module Array

from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val composed : (int list -> int list)

Full name: FSharpBasicsEng.composed
val map : mapping:('T -> 'U) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
val emptyList2 : bigint list

Full name: FSharpBasicsEng.emptyList2
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
type bigint = System.Numerics.BigInteger

Full name: Microsoft.FSharp.Core.bigint
val emptyList3 : bigint list

Full name: FSharpBasicsEng.emptyList3
val tuple : int * string * float

Full name: FSharpBasicsEng.tuple
val a : int

Full name: FSharpBasicsEng.a
val b : string

Full name: FSharpBasicsEng.b
val c : float

Full name: FSharpBasicsEng.c
val myInstance1 : UserData1

Full name: FSharpBasicsEng.myInstance1
Multiple items
type UserData2 =
  new : unit -> UserData2
  new : email:string -> UserData2
  member Email : string

Full name: FSharpBasicsEng.UserData2

--------------------
new : unit -> UserData2
new : email:string -> UserData2
val email : string
val x : UserData2
member UserData2.Email : string

Full name: FSharpBasicsEng.UserData2.Email
Multiple items
type Base =
  new : unit -> Base
  abstract member Method : unit -> unit
  override Method : unit -> unit

Full name: FSharpBasicsEng.Base

--------------------
new : unit -> Base
val DoSomething : (unit -> unit)
abstract member Base.Method : unit -> unit

Full name: FSharpBasicsEng.Base.Method
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val x : Base
override Base.Method : unit -> unit

Full name: FSharpBasicsEng.Base.Method
val x : My inherited class with dispose
override My inherited class with dispose.Method : unit -> unit

Full name: FSharpBasicsEng.My inherited class with dispose.Method
override My inherited class with dispose.Dispose : unit -> 'a

Full name: FSharpBasicsEng.My inherited class with dispose.Dispose
type myEnum =
  | A
  | B

Full name: FSharpBasicsEng.myEnum
union case myEnum.A: myEnum
union case myEnum.B: myEnum
type CalendarEvent =
  | ExactTime of obj
  | MonthAndYear of string * int

Full name: FSharpBasicsEng.CalendarEvent
union case CalendarEvent.ExactTime: obj -> CalendarEvent
union case CalendarEvent.MonthAndYear: string * int -> CalendarEvent
type Tree =
  | Leaf of int
  | Node of Tree * Tree

Full name: FSharpBasicsEng.Tree
union case Tree.Leaf: int -> Tree
union case Tree.Node: Tree * Tree -> Tree
type aliasItem<'a,'b> = System.Collections.Generic.KeyValuePair<'a,'b>

Full name: FSharpBasicsEng.aliasItem<_,_>
namespace System.Collections
namespace System.Collections.Generic
Multiple items
type KeyValuePair<'TKey,'TValue> =
  struct
    new : key:'TKey * value:'TValue -> KeyValuePair<'TKey, 'TValue>
    member Key : 'TKey
    member ToString : unit -> string
    member Value : 'TValue
  end

Full name: System.Collections.Generic.KeyValuePair<_,_>

--------------------
System.Collections.Generic.KeyValuePair()
System.Collections.Generic.KeyValuePair(key: 'TKey, value: 'TValue) : unit
type OrderId = | Id of Guid

Full name: FSharpBasicsEng.OrderId
union case OrderId.Id: System.Guid -> OrderId
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 Address =
  {Street: string;
   Zip: int;
   City: string;}

Full name: FSharpBasicsEng.Address
Address.Street: string
Address.Zip: int
Address.City: string
val myAddrr : Address

Full name: FSharpBasicsEng.myAddrr
Multiple items
type MeasureAttribute =
  inherit Attribute
  new : unit -> MeasureAttribute

Full name: Microsoft.FSharp.Core.MeasureAttribute

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

Full name: FSharpBasicsEng.EUR
[<Measure>]
type LTC

Full name: FSharpBasicsEng.LTC
val rate : decimal<EUR/LTC>

Full name: FSharpBasicsEng.rate
val ratePlain : decimal
val myMoneyInEur : x:decimal<LTC> -> decimal<EUR>

Full name: FSharpBasicsEng.myMoneyInEur
val x : decimal<LTC>
val converted : decimal<EUR>

Full name: FSharpBasicsEng.converted
val MyFunction1 : a:string -> int

Full name: FSharpBasicsEng.MyFunction1
val a : string
val MyFunction2 : a:string -> int

Full name: FSharpBasicsEng.MyFunction2
val MyFunction3 : a:string -> int

Full name: FSharpBasicsEng.MyFunction3
val MyFunction4 : _arg1:string -> int

Full name: FSharpBasicsEng.MyFunction4
val MyFunction5 : a:string -> int

Full name: FSharpBasicsEng.MyFunction5
val x : string
val MyFunction6 : a:string -> int

Full name: FSharpBasicsEng.MyFunction6
val p : string
active recognizer FirstVowel: string -> Choice<unit,unit,unit>
active recognizer FirstConsonant: string -> Choice<unit,unit,unit>
active recognizer Other: string -> Choice<unit,unit,unit>
val echo : x:'a -> string

Full name: FSharpBasicsEng.echo
val x : 'a
System.Object.ToString() : string
val ( working hours ) : float option

Full name: FSharpBasicsEng.( working hours )
val day : int
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end

Full name: System.DateTime

--------------------
System.DateTime()
   (+0 other overloads)
System.DateTime(ticks: int64) : unit
   (+0 other overloads)
System.DateTime(ticks: int64, kind: System.DateTimeKind) : unit
   (+0 other overloads)
System.DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
System.DateTime(year: int, month: int, day: int, calendar: System.Globalization.Calendar) : unit
   (+0 other overloads)
System.DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
System.DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: System.DateTimeKind) : unit
   (+0 other overloads)
System.DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: System.Globalization.Calendar) : unit
   (+0 other overloads)
System.DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
System.DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: System.DateTimeKind) : unit
   (+0 other overloads)
property System.DateTime.Now: System.DateTime
property System.DateTime.DayOfWeek: System.DayOfWeek
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val echoHours1 : string

Full name: FSharpBasicsEng.echoHours1
val h : float
val echoHours2 : string option

Full name: FSharpBasicsEng.echoHours2
module Option

from Microsoft.FSharp.Core
val map : mapping:('T -> 'U) -> option:'T option -> 'U option

Full name: Microsoft.FSharp.Core.Option.map
val echoHours3 : string option

Full name: FSharpBasicsEng.echoHours3
val sumItems : myList:int list -> int

Full name: FSharpBasicsEng.sumItems
val myList : int list
val calculate : (int list -> int -> int)
val li : int list
val acc : int
val h : int
val t : int list
val asyncOperation : Async<unit>

Full name: FSharpBasicsEng.asyncOperation
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.Sleep : millisecondsDueTime:int -> Async<unit>
val waitAndReturn : Async<float>

Full name: FSharpBasicsEng.waitAndReturn
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val waitAndReturn2 : Async<float>

Full name: FSharpBasicsEng.waitAndReturn2
val x : float
val y : float
val sum : float
val result : float

Full name: FSharpBasicsEng.result
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:System.Threading.CancellationToken -> 'T
val slice : mySeq:seq<int> -> seq<System.Collections.Generic.IEnumerable<int>>

Full name: FSharpBasicsEng.slice
val mySeq : seq<int>
val chunkSize : int
val seqSlice : (seq<int> -> seq<System.Collections.Generic.IEnumerable<int>>)
val s : seq<int>
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<_>
(extension) System.Collections.Generic.IEnumerable.Skip<'TSource>(count: int) : System.Collections.Generic.IEnumerable<'TSource>

Creative Commons -copyright Tuomas Hietanen, 2014, thorium(at)iki.fi, Creative Commons