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
