F# (pronounced F sharp) is a general-purpose, high-level, strongly typed, multi-paradigm programming language that encompasses functional, imperative, and object-oriented programming methods. It is most often used as a cross-platform Common Language Infrastructure (CLI) language on .NET, but can also generate JavaScript and graphics processing unit (GPU) code.

F# is developed by the F# Software Foundation, Microsoft and open contributors. An open source, cross-platform compiler for F# is available from the F# Software Foundation. F# is a fully supported language in Visual Studio and JetBrains Rider. Plug-ins supporting F# exist for many widely used editors including Visual Studio Code, Vim, and Emacs.

F# is a member of the ML language family and originated as a .NET Framework implementation of a core of the programming language OCaml.

|Windows

|.NET 1.0 - 3.5

|-

| 2.0

| August 2010

| April 2010

|Linux, macOS, Windows

|.NET 2.0 - 4.0, Mono

|-

| 3.0

| November 2012

| August 2012

|Linux, macOS, Windows;<br/>JavaScript,

|Linux, macOS, Windows;<br/>JavaScript,

|<!-- Linux, macOS, Windows;<br/>JavaScript, GPU -->

|<!-- .NET 2.0 - 4.5, Mono -->

|-

| 4.1

| May 2018

|March 2017

|Linux, macOS, Windows,

JavaScript,

|Linux, macOS, Windows,

JavaScript, .NET Core SDK 2.1.400

|-

| 4.6

|

|March 2019

|Linux, macOS, Windows,

JavaScript, .NET Core SDK 2.2.300

|-

| 4.7

|

|September 2019

|Linux, macOS, Windows,

JavaScript, .NET Core SDK 3.0.100

|-

| 5.0

|

|November 2020

|Linux, macOS, Windows,

JavaScript,

|-

| 6.0

|

|November 2021

|Linux, macOS, Windows,

JavaScript,

|-

| 7.0

|

|November 2022

|Linux, macOS, Windows,

JavaScript,

|-

| 8.0

|

|November 2023

|Linux, macOS, Windows,

JavaScript,

|-

| 9.0

|

|November 2024

|Linux, macOS, Windows,

JavaScript,

|-

|10.0

|

|November 2025

|Linux, macOS, Windows,

JavaScript,

|}

Language evolution

F# uses an open development and engineering process.

The language evolution process is managed by Don Syme from Microsoft Research as the benevolent dictator for life (BDFL) for the language design, together with the F# Software Foundation.

Earlier versions of the F# language were designed by Microsoft and Microsoft Research using a closed development process.

F# was first included in Visual Studio in the 2010 edition, at the same level as Visual Basic (.NET) and C# (albeit as an option), and remains in all later editions, thus making the language widely available and well-supported.

F# originates from Microsoft Research, Cambridge, UK. The language was originally designed and implemented by Don Syme, according to whom in the fsharp team, they say the F is for "Fun".

Andrew Kennedy contributed to the design of units of measure.

|

  • Type providers
  • LINQ query expressions
  • CLIMutable attribute
  • Triple-quoted strings
  • Auto-properties
  • Provided units-of-measure

|-

! 3.1

|

  • Named union type fields
  • Extensions to array slicing
  • Type inference enhancements

|-

! 4.0

|

  • Printf on unitized values
  • Extension property initializers
  • Non-null provided types
  • Primary constructors as functions
  • Static parameters for provided methods
  • Printf interpolation
  • Extended #if grammar
  • Tailcall attribute
  • Multiple interface instantiations
  • Optional type args
  • Params dictionaries

|-

! 4.1

|

  • Struct tuples which inter-operate with C# tuples
  • Struct annotations for Records
  • Struct annotations for Single-case Discriminated Unions
  • Underscores in numeric literals
  • Caller info argument attributes
  • Result type and some basic Result functions
  • Mutually referential types and modules within the same file
  • Implicit "Module" syntax on modules with shared name as type
  • Byref returns, supporting consuming C# ref-returning methods
  • Error message improvements
  • Support for 'fixed'

|-

! 4.5

|

  • Implicit yields
  • No more required double underscore
  • Indentation relaxations for parameters passed to constructors and static methods
  • 'nameof' function
  • Open static classes

|-

! 5.0

|

  • FSharp.Core now targets netstandard2.0 only
  • Package references in F# scripts
  • Support for Jupyter, nteract, and VSCode Notebooks
  • String Interpolation
  • Support for nameof
  • Open Type declarations
  • Enhanced Slicing
  • F# quotations improvements
  • Applicative Computation Expressions
  • Improved stack traces in F# async and other computation expressions
  • Improved .NET interop
  • Improved Map and Set performance in FSharp.Core
  • Improved compiler performance
  • Improved compiler analysis for library authors

|-

! 6.0

|

  • Tasks
  • Simpler indexing
  • Augments to "active patterns"
  • Overloaded custom operations in computation expressions
  • “as” patterns
  • Indentation syntax revisions
  • More implicit conversions
  • More implicit upcast conversions
  • Implicit integer conversions
  • First-class support for .NET-style implicit conversions
  • Optional warnings for implicit conversions
  • Formatting for binary numbers
  • Discards on use bindings
  • InlineIfLambda optimizer directive
  • Resumable code
  • More collection functions
  • Map has Keys and Values
  • More intrinsics for NativePtr
  • More numeric types with unit annotations
  • Informational warnings for rarely used symbolic operators

|-

! 7.0

|

  • Static abstract members support in interfaces
  • Making working with SRTPs (statically resolved type parameters) easier
  • Required properties checking
  • Init scope and init-only properties
  • Reference assemblies support
  • F# self-contained deployments & Native AOT
  • Added support for N-d arrays up to rank 32.
  • Result module functions parity with Option.
  • Fixes in resumable state machines codegen for the tasks builds.
  • Better codegen for compiler-generated side-effect-free property getters
  • ARM64 platform-specific compiler and ARM64 target support in F# compiler. Dependency manager #r caching support
  • Parallel type-checking and project-checking support (experimental, can be enabled via VS setting, or by tooling authors)
  • Miscellaneous bugfixes and improvements.

|-

! 8.0

|

  • _.Property shorthand for (fun x -> x.Property)
  • Nested record field copy and update
  • while! (while bang) feature
  • Extended string interpolation syntax
  • Use and compose string literals for printf and related functions
  • Arithmetic operators in literals
  • Type constraint intersection syntax
  • Extended fixed binding
  • Easier [<Extension>] method definition
  • Static members in interfaces
  • Static let in discriminated unions, records, structs, and types without primary constructors
  • try-with within seq{}, [], and [||] collection expressions
  • Recursive calls and yield! within exception handler
  • Tail call attribute
  • [<Struct>] unions can now have > 49 cases
  • Strict indentation rules
  • New diagnostics from the compiler
  • Switches for compiler parallelization

|-

! 9.0

|

  • Nullable reference types
  • Discriminated union .Is* properties
  • Partial active patterns can return bool instead of unit option
  • Prefer extension methods to intrinsic properties when arguments are provided
  • Empty-bodied computation expressions
  • Hash directives are allowed to take non-string arguments
  • Extended #help directive in fsi to show documentation in the REPL
  • Allow #nowarn to support the FS prefix on error codes to disable warnings
  • Warning about TailCall attribute on non-recursive functions or let-bound values
  • Enforce attribute targets
  • Updates to the standard library (FSharp.Core)
  • Developer productivity improvements
  • Performance improvements
  • Improvements in tooling

|-

!10.0)

  • Tail call optimisation

F# is an expression-based language using eager evaluation and also in some instances lazy evaluation. Every statement in F#,

including <code>if</code> expressions, <code>try</code> expressions and loops, is a composable expression with a static type. For example:

<syntaxhighlight lang="fsharp">

let x = 3 + 4

</syntaxhighlight>

binds the value <code>7</code> to the name <code>x</code>.

New types are defined using the <code>type</code> keyword. For functional programming, F# provides tuple, record, discriminated union, list, option, and result types.

Imperative programming

F# support for imperative programming includes

  • <code>for</code> loops
  • <code>while</code> loops
  • arrays, created with the <code>[| ... |]</code> syntax
  • hash table, created with the <code>dict [ ... ]</code> syntax or <code>System.Collections.Generic.Dictionary<_,_></code> type.

Values and record fields can also be labelled as <code>mutable</code>. For example:

<syntaxhighlight lang="fsharp">

// Define 'x' with initial value '1'

let mutable x = 1

// Change the value of 'x' to '3'

x <- 3

</syntaxhighlight>

Also, F# supports access to all CLI types and objects such as those defined in the <code>System.Collections.Generic</code> namespace defining imperative data structures.

Object-oriented programming

Like other Common Language Infrastructure (CLI) languages, F# can use CLI types through object-oriented programming.

F# object type definitions can be class, struct, interface, enum, or delegate type definitions, corresponding to the definition forms found in C#. For example, here is a class with a constructor taking a name and age, and declaring two properties.

<syntaxhighlight lang="fsharp">

/// A simple object type definition

type Person(name : string, age : int) =

member x.Name = name

member x.Age = age

</syntaxhighlight>

Asynchronous programming

F# supports asynchronous programming through asynchronous workflows.

Inversion of control in F# follows this pattern.

<syntaxhighlight lang="fsharp">

open System.Net.Http

let fetchUrlAsync (url:string) = // string -> Task<string>

task {

use client = new HttpClient()

let! response = client.GetAsync(url)

let! content = response.Content.ReadAsStringAsync()

do! Task.Delay 500

return content

}

// Usage

let fetchPrint() =

let task = task {

let! data = fetchUrlAsync "https://example.com"

printfn $"{data}"

}

task.Wait()

</syntaxhighlight>

Parallel programming

Parallel programming is supported partly through the <code>Async.Parallel</code>, <code>Async.Start</code> and other operations that run asynchronous blocks in parallel.

Parallel programming is also supported through the <code>Array.Parallel</code> functional programming operators in the F# standard library, direct use of the <code>System.Threading.Tasks</code> task programming model, the direct use of .NET thread pool and .NET threads and through dynamic translation of F# code to alternative parallel execution engines such as GPU units of measure, such as meters or kilograms, can be assigned to floating point, unsigned integer and signed integer values. This allows the compiler to check that arithmetic involving these values is dimensionally consistent, helping to prevent common programming mistakes by ensuring that, for instance, lengths are not mistakenly added to times.

The units of measure feature integrates with F# type inference to require minimal type annotations in user code.

<syntaxhighlight lang="fsharp">

[<Measure>] type m // meter

[<Measure>] type s // second

let distance = 100.0<m> // float<m>

let time = 5.0<s> // float<s>

let speed = distance/time // float<m/s>

[<Measure>] type kg // kilogram

[<Measure>] type N = (kg * m)/(s^2) // Newtons

[<Measure>] type Pa = N/(m^2) // Pascals

[<Measure>] type days

let better_age = 3u<days> // uint<days>

</syntaxhighlight>

The F# static type checker provides this functionality at compile time, but units are erased from the compiled code. Consequently, it is not possible to determine a value's unit at runtime.

Metaprogramming

F# allows some forms of syntax customizing via metaprogramming to support embedding custom domain-specific languages within the F# language, particularly through computation expressions. A quotation expression evaluates to an abstract syntax tree representation of the F# expressions. Similarly, definitions labelled with the <code>[&lt;ReflectedDefinition&gt;]</code> attribute can also be accessed in their quotation form. F# quotations are used for various purposes including to compile F# code into JavaScript F# type providers allow the F# compiler and tools to be extended with components that provide type information to the compiler on-demand at compile time. F# type providers have been used to give strongly typed access to connected information sources in a scalable way, including to the Freebase knowledge graph.

In F# 3.0 the F# quotation and computation expression features are combined to implement LINQ queries. For example:

<syntaxhighlight lang="fsharp">

// Use the OData type provider to create types that can be used to access the Northwind database.

open Microsoft.FSharp.Data.TypeProviders

type Northwind = ODataService<"http://services.odata.org/Northwind/Northwind.svc">

let db = Northwind.GetDataContext()

// A query expression.

let query1 = query { for customer in db.Customers do

select customer }

</syntaxhighlight>

The combination of type providers, queries and strongly typed functional programming is known as information rich programming.

Agent programming

F# supports a variation of the actor programming model through the in-memory implementation of lightweight asynchronous agents. For example, the following code defines an agent and posts 2 messages:

<syntaxhighlight lang="fsharp">

type Message =

| Enqueue of string

| Dequeue of AsyncReplyChannel<Option<string>>

// Provides concurrent access to a list of strings

let listManager = MailboxProcessor.Start(fun inbox ->

let rec messageLoop list = async {

let! msg = inbox.Receive()

match msg with

| Enqueue item ->

return! messageLoop (item :: list)

| Dequeue replyChannel ->

match list with

| [] ->

replyChannel.Reply None

return! messageLoop list

| head :: tail ->

replyChannel.Reply (Some head)

return! messageLoop tail

}

// Start the loop with an empty list

messageLoop []

)

// Usage

async {

// Enqueue some strings

listManager.Post(Enqueue "Hello")

listManager.Post(Enqueue "World")

// Dequeue and process the strings

let! str = listManager.PostAndAsyncReply(Dequeue)

str |> Option.iter (printfn "Dequeued: %s")

}

|> Async.Start

</syntaxhighlight>

Development tools

  • Visual Studio, with the Visual F# tools from Microsoft installed, can be used to create, run and debug F# projects. The Visual F# tools include a Visual Studio-hosted read–eval–print loop (REPL) interactive console that can execute F# code as it is written. Visual Studio for Mac also fully supports F# projects.
  • Visual Studio Code contains full support for F# via the Ionide extension.
  • F# can be developed with any text editor. Specific support exists in editors such as Emacs.
  • JetBrains Rider is optimized for the development of F# Code starting with release 2019.1.
  • LINQPad has supported F# since version 2.x.

Comparison of integrated development environments

Application areas

F# is a general-purpose programming language.

Web programming

The SAFE Stack is an end-to-end F# stack to develop web applications. It uses ASP.NET Core on the server side and Fable on the client side.

Alternative end-to-end F# options include the WebSharper framework and the Oxpecker framework.

Cross-platform app development

F# can be used together with the Visual Studio Tools for Xamarin to develop apps for iOS and Android. The Fabulous library provides a more comfortable functional interface.

Analytical programming

Among others, F# is used for quantitative finance programming, energy trading and portfolio optimization, machine learning, business intelligence and social gaming on Facebook.

In the 2010s, F# has been positioned as an optimized alternative to C#. F#'s scripting ability and inter-language compatibility with all Microsoft products have made it popular among developers.

Scripting

F# can be used as a scripting language, mainly for desktop read–eval–print loop (REPL) scripting.

Open-source community

The F# open-source community includes the F# Software Foundation