A Public Preview Announcement

On January 5, 2005, Don Syme announced that the F# 1.0 preview was available to download. He explained that the announcement followed the software’s appearance because download problems needed attention. The notice described F# as a Microsoft Research project. Version 1.0 was a language and toolset still undergoing experimentation: users could obtain its compiler, libraries, and development-environment extensions and report problems to its designers.

The release included object expressions, mutually recursive reactive values, and the lexer and parser generators fslex and fsyacc. It generated code using generics while retaining a nongeneric code path for earlier .NET versions. The release therefore addressed both language expressiveness and compatibility with the existing platform.

References: [1]

The Cambridge Research Team

F# emerged from work at Microsoft Research in Cambridge on combining functional languages with the .NET runtime. Syme drew on OCaml’s core language, initially writing the compiler in OCaml and targeting .NET. An early version, 0.1, was released with the ILX project on June 4, 2002. The design shared .NET data representations and exception mechanisms so that F# and languages such as C# could call one another.

After completing an initial phase of work on .NET generics, Syme increased his work on F# in 2004. James Margetson joined in March 2005, contributing performance testing and support for internal projects. The team tested the language against existing OCaml code, including the Stochastic Pi Machine, the Static Driver Verifier, and Terminator. Problems encountered during these ports helped establish whether the implementation was usable.

References: [2]

Type Checking in Short Scripts

In his 2005 technical article, Syme described scientists who wanted to experiment as quickly as they could with mathematical scripting tools, while developing their results into programs with dependable performance. F# used functions, tuples, lists, and pattern matching as basic forms of expression. It also called existing .NET libraries for graphical interfaces, files, and other tasks, reducing the need to rebuild an entire software ecosystem for a new language.

Its concise syntax relied on type inference. The compiler gathered constraints from operations and function calls to determine input and result types, reporting errors when those constraints conflicted. For example, a function taking a string and returning two counts could have the type “string to integer pair.” The compiler could check calls for consistency even when the programmer did not explicitly declare every type.

References: [3]

Three Numbers Around Their Mean

The 2005 article presented a function called DistanceFromAverage. It first computed the mean, avg, of three numbers a, b, and c. An inner function, diff, squared a number’s difference from avg; the function then took the square root of the sum of the three squared differences. The inner function used avg from the enclosing scope, without requiring the mean to be passed into every call.

For 1.0, 2.0, and 3.0, the mean is 2.0 and the squared differences are 1, 0, and 1, giving a result of the square root of 2. The example brought together local functions, lexical scope, and the .NET square-root function. It computed the length of the deviation vector. Its operations determined the required floating-point types, combining concise code with compile-time checking.

References: [3]

Data Models and Development Tools

For symbolic computation, F# could define an expression as one of several distinct forms, such as a constant, a sum, or a product. Pattern matching distinguished these cases and recursively processed their subexpressions. Such discriminated unions encoded the permitted forms in the data definition itself, making them useful for syntax trees and other branching structures.

Development tools were also taking shape. The Visual Studio extension accompanying the January announcement required Visual Studio 2005 Beta 1 and its associated SDK. It supported syntax coloring, parsing, type checking, and preliminary project management; IntelliSense remained planned. Integration with an existing environment let programmers try the language using familiar editing and project workflows.

References: [1] [3]

Queries and Program Fragments

Research in 2006 further explored quotations: preserving type-checked F# expressions as structures that other execution components could analyze. In his ML workshop paper, Syme demonstrated selecting employees who lived in London and retrieving their addresses. LINQ components translated the program’s conditions and selections into SQL for execution by the database.

The paper also explored running data-parallel programs on graphics processors through Accelerator and dynamically generating native code with LINQ components. These later experiments extended .NET interoperability beyond calling existing functions to connecting databases, graphics processors, and native code.

References: [4]