liveBook · Manning

F# syntax

As explained in F# in Action: A Revised Edition of Get Programming with F#

F# syntax is the set of lexical and grammatical rules that determine how F# programs are written and parsed.

F# syntax aims for succinct, readable, type-safe code rather than brevity for its own sake. It removes many symbols, keywords, and ceremony, leaving more of a program devoted to business logic. Human-readable functions can replace symbolic operators, and lightweight forms can support domain-specific languages that stakeholders can read. section 3.1.1 section 1.6

The central keyword is let. Use it to bind a value or define a function; bindings are immutable. Indentation creates scope, making a symbol’s visibility and lifetime apparent without explicit block delimiters. Type inference commonly supplies types that would otherwise need to be written out. section 3.4

Start with the idiomatic form

A function can take arguments directly after its name, use indented local bindings, and return its final expression: let addTenThenDouble theNumber = let addedTen = theNumber + 10 let answer = addedTen * 2 printfn $"({theNumber} + 10) * 2 is {answer}" answer Here, let defines both the function and local values. No braces, semicolons, explicit return, or repeated type annotations are needed; inference determines the numeric types, while the final expression supplies the result. section 3.4

Listing 3.2 A verbose version of F# syntax basics
let addTenThenDouble (theNumber : int) : int =                          #1
{                                                                       #2
    let addedTen : int = theNumber + 10;                                #3
    let answer : int = addedTen * 2;
    printfn $"({theNumber} + 10) * 2 is {answer}";
    let website : System.Uri = new System.Uri ("https://fsharp.org");   #4
    return answer;                                                      #5
}

Compare this deliberately verbose version with the idiomatic listing to identify ceremony F# normally omits: explicit types, braces, semicolons, constructor syntax, and return. section 3.1.1

Use the syntax conventions as practical reading guides:

  • Read indentation as scope before looking for explicit delimiters. section 3.4
  • Expect inferred types unless an annotation is useful for clarity or required by a context. section 3.4
  • Prefer the lightweight form when it expresses the same intent without extra boilerplate. section 3.1.1
  • Inspect inferred types and errors with IDE support such as VS Code and CodeLens. section 3.4

How F# in Action: A Revised Edition of Get Programming with F# covers it

How deep it goes
Explains bindings, indentation-based scopes, and inferred types, while deferring broader application structure.
Examples
Contrasts an indented add-and-double function with a verbose form using annotations, braces, semicolons, and return.
What it assumes
Builds from simple F# written with prior tooling exposure and assumes no prior F# or .NET knowledge.
What you can do after
Evaluate/understand concise F# definitions, scopes, and inferred types in routine code.
How it connects
Connects let bindings and scopes with immutability, type inference, refactoring, DSLs, and IDE support.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of F# in Action: A Revised Edition of Get Programming with F#. The section links point to the parts of the book it draws on.