F#
F# was designed by Don Syme at Microsoft Research, with a first release in 2005. It is a descendant of ML and OCaml, running on the same .NET platform as C#. It is functional first, but it has full support for classes and interfaces when you need them.
Paradigm: Object-Functional and Beyond
What Makes F# Special
- Functional first. Values are immutable by default, functions are curried, and the pipe operator
|>passes the result of one step into the next. - Type inference. Almost no type annotations are needed. The compiler infers types, including generic ones, from how values are used.
- Discriminated unions and pattern matching. A union type lists its cases, each with data.
matchchecks all cases, and incomplete matches produce a warning. - Units of measure. Numbers can carry units such as
mors. The compiler checks that you never add metres to seconds, and it computes derived units likem/s. - Objects when needed. Classes, interfaces and mutable fields exist, so F# can use any .NET library and be used from C#.
- Computation expressions and type providers. Computation expressions (
async { },seq { }) are a general syntax for workflows, and type providers generate types from data sources.
Example: Unions, pipelines, units of measure and a class
type Shape =
| Circle of float
| Rect of float * float
let area shape =
match shape with
| Circle r -> System.Math.PI * r * r
| Rect (w, h) -> w * h
let shapes = [ Circle 1.0; Rect (2.0, 3.0) ]
// pipeline: the result of each step feeds the next
let total = shapes |> List.map area |> List.sum
printfn "%.2f" total // 9.14
// units of measure
[<Measure>] type m
[<Measure>] type s
let distance = 100.0<m>
let time = 9.58<s>
let speed = distance / time // float<m/s>
printfn "%.2f" (float speed) // 10.44
// an object with mutable state
type Counter() =
let mutable n = 0
member _.Next() =
n <- n + 1
n
let c = Counter()
c.Next() |> ignore
printfn "%d" (c.Next()) // 2
How It Works
Shapeis a discriminated union, andareais inferred asShape -> floatwith no annotation.shapes |> List.map area |> List.sumreads like a sentence and needs no temporary variables.distance / timehas typefloat<m/s>. Writingdistance + timewould not compile. Units exist only at compile time and cost nothing at run time.Counteris an ordinary class with a mutable field, so F# code can also be object-oriented and imperative.
History and Where It Is Used
F# is used in finance and data analysis, compilers and language tools, scientific computing and web back ends (with frameworks such as Giraffe and Fable, which compiles F# to JavaScript). It is often the first way a .NET team adopts functional programming, since it shares libraries and tooling with C#.