Introduction
F# is a functional-first, statically typed language for the .NET platform. Its source files are UTF-8 text: .fs files are compiled in the order a project lists them, .fsi files are signature files that say what a matching .fs file shows to the outside, and .fsx files (also .fsscript) are scripts that dotnet fsi runs. The language is described by the open F# language specification and developed in the open on GitHub.
The syntax is light: blocks are made by indentation (the offside rule) instead of braces or begin and end, and names are bound with let. A program is a list of modules and namespaces holding values, functions and types. These pages describe the files, the lexical forms the scanner of this site reads, every kind of type and expression, patterns, computation expressions, quotations, type providers, the library, the compiler directives, the versions of the language and the tools.
module Shapes
/// A shape with its size.
type Shape =
| Circle of radius: float
| Rect of width: float * height: float
let area shape =
match shape with
| Circle r -> System.Math.PI * r * r
| Rect (w, h) -> w * h
[<EntryPoint>]
let main _ =
[ Circle 1.0; Rect (2.0, 3.0) ]
|> List.sumBy area
|> printfn "total area %.2f"
0
The kinds of file
| Extension | What it is | Page |
|---|---|---|
.fs | implementation file: a module or one or more namespaces; compiled in project order | File structure |
.fsi | signature file: the public signature of the .fs file of the same name | File structure |
.fsx, .fsscript | script: top-level code run by F# Interactive, with #r and #load directives | Directives |
.fsproj | the project file that lists the sources and the packages: MSBuild XML, not F# (a later item on this site) | Tooling |
How the viewer reads each file
A file is shown as coloured text, with its own name for the kind of file it is. The scanner follows the lexer of the F# compiler: nested comments that read the strings inside them, every string form including interpolated and triple-quoted ones with their holes, every numeric suffix, characters against type variables, the directives and the attributes. It also keeps a small context so that it can tell types, bound names and calls from other names (see the lexical structure page).
| File | Shown as | Page |
|---|---|---|
.fs | F# source file when the text opens with F# declarations; GLSL fragment shader when it has the markers of GLSL (many tools use .fs for those); otherwise a text file with an .fs extension (Forth, for example), shown without colour | File structure |
.fsi | F# signature file | File structure |
.fsx, .fsscript | F# script | Directives |
Not described
Known, not yet covered
- Reference: the sources read were the language specification (Markdown source of the 4.1 text with later changes), the lexer, parser and keyword table of the compiler, the language-feature table of the compiler (F# 4.6 to 11.2), the F# language reference and tools pages of the Microsoft documentation (about 165 files, read in part), the FSharp.Core interface files and the language design RFC folders (the folder names and the ones quoted on the pages; most RFCs were not read in full). What each page leaves out is on that page.
- Reference: only the file structure and lexical structure pages were read in full a second time after they were written. The tables of the other pages (the constraints, the pattern forms, the computation expression methods and query operators, the quotation names, the printf specifiers, the library function names, the version table) were checked against the downloaded sources while they were written; the prose and the examples around them were not re-read and may hold slips. The F# 1.0 to 3.1 entries of the versions page are from memory.
- Reference: the F# language specification PDF, the grammar of
pars.fsybeyond the productions quoted, the whole offside rule ofLexFilter.fs, the documentation text of every library function and the compiler messages (FS0001 and the rest) are not covered. - Viewer: the colouring follows the text and not the program. It does not know which defines are set, so both sides of
#ifare read as code; names are told apart by their place (after a colon, in a pattern, before a bracket), so a function that is passed on without a bracket (f x) and a value whose name starts with a capital letter are not told apart from a type or a union case; the custom operations of query expressions (select,where) are not coloured; the offside rule is not followed beyond ending a type or a binding at the end of its line, so a type that continues on the next line with anything other than->or*is cut short.
Unknown
- Viewer: the scanner was tested on hand-written cases for every token form, on one-megabyte worst cases and on the F# found for the purpose (FSharp.Core, the compiler, Paket, FAKE, FsAutoComplete, Fantomas and one sample in the Ace editor). No other F# was on this Mac, so how the context rules fare on code in other styles, and on very large generated files, is not known.
- Reference: no .NET SDK was available on this Mac, so no F# example on these pages was compiled or run; they were checked by reading, and the colouring of each was checked by the scanner.
Links
Software
Developers
- dotnet/fsharp – the F# compiler, F# Interactive and FSharp.Core (F#)
- FsAutoComplete – the language server behind Ionide (F#)
Reference
- F# documentation – Microsoft’s guide and language reference
- F# language specification – the specification as Markdown
- F# language design – the RFCs for every language change since F# 4.0