What is F#

F# is a universal programming language for writing succinct, robust and performant code.

F# allows you to write uncluttered, self-documenting code, where your focus remains on your problem domain, rather than the details of programming.

It does this without compromising on speed and compatibility - it is open-source, cross-platform and interoperable.

open System // Gets access to functionality in System namespace.

// Defines a list of names
let names = [ "Peter"; "Julia"; "Xi" ]

// Defines a function that takes a name and produces a greeting.
let getGreeting name = $"Hello, {name}"

// Prints a greeting for each name!
|> List.map getGreeting
|> List.iter (fun greeting -> printfn $"{greeting}! Enjoy your F#")

F# has numerous features, including:

  • Lightweight syntax
  • Immutable by default
  • Type inference and automatic generalization
  • First-class functions
  • Powerful data types
  • Pattern matching
  • Async programming

A full set of features are documented in the F# language guide.

Rich data types

Types such as Records and Discriminated Unions let you represent your data.

// Group data with Records
type SuccessfulWithdrawal =
    { Amount: decimal
      Balance: decimal }

type FailedWithdrawal =
    { Amount: decimal
      Balance: decimal
      IsOverdraft: bool }

// Use discriminated unions to represent data of 1 or more forms
type WithdrawalResult =
    | Success of SuccessfulWithdrawal
    | InsufficientFunds of FailedWithdrawal
    | CardExpired of System.DateTime
    | UndisclosedFailure

F# records and discriminated unions are non-null, immutable, and comparable by default, making them very easy to use.

Correctness with functions and pattern matching

F# functions are easy to define. When combined with pattern matching, they allow you to define behavior whose correctness is enforced by the compiler.

// Returns a WithdrawalResult
let withdrawMoney amount = // Implementation elided

let handleWithdrawal amount =
    let w = withdrawMoney amount

    // The F# compiler enforces accounting for each case!
    match w with
    | Success s -> printfn $"Successfully withdrew %f{s.Amount}"
    | InsufficientFunds f -> printfn $"Failed: balance is %f{f.Balance}"
    | CardExpired d -> printfn $"Failed: card expired on {d}"
    | UndisclosedFailure -> printfn "Failed: unknown :("

F# functions are also first-class, meaning they can be passed as parameters and returned from other functions.

Functions to define operations on objects

F# has full support for objects, which are useful when you need to blend data and functionality. F# members and functions can be defined to manipulate objects.

type Set<'T when 'T: comparison>(elements: seq<'T>) =
    member s.IsEmpty = // Implementation elided
    member s.Contains (value) =// Implementation elided
    member s.Add (value) = // Implementation elided
    // ...
    // Further Implementation elided
    // ...
    interface IEnumerable<'T>
    interface IReadOnlyCollection<'T>

module Set =
    let isEmpty (set: Set<'T>) = set.IsEmpty

    let contains element (set: Set<'T>) = set.Contains(element)

    let add value (set: Set<'T>) = set.Add(value)

In F#, you will often write code that treats objects as a type for functions to manipulate. Features such as generic interfaces, object expressions, and judicious use of members are common in larger F# programs.

Next steps

To learn more about a larger set of F# features, check out the F# Tour.