F# Verbose Syntax
last modified May 24, 2025
This article explores verbose syntax in F#, which provides explicit syntax rules for situations where lightweight syntax might be ambiguous.
F# supports two syntax variants: lightweight and verbose. Verbose syntax requires more keywords but can resolve ambiguities in complex code. It's particularly useful in interface implementations, type extensions, and certain expressions.
Verbose syntax is always available, allowing you to use it alongside lightweight syntax for certain constructs. While not as commonly used, verbose syntax offers the benefit of being less dependent on indentation, making it more forgiving in structured code layouts.
The main differences include using in
keywords after bindings,
explicit then
in conditionals, and done
in loops.
Enabling verbose syntax
Verbose syntax can be enabled for entire files or specific code sections.
let add x y = begin x + y end printfn "Result: %d" (add 5 3)
This example shows verbose syntax in a function definition.
let add x y = begin x + y end
The begin
and end
keywords explicitly mark the
function body, which is a requirement in verbose syntax.
λ dotnet fsi main.fsx Result: 8
Let bindings in verbose syntax
Verbose syntax requires the in
keyword for sequential let bindings.
let calculate x y = let sum = x + y in let product = x * y in sum, product let result = calculate 3 4 printfn "Sum: %d, Product: %d" (fst result) (snd result)
This demonstrates verbose let bindings with mandatory in
keywords.
let sum = x + y in let product = x * y in
Each let
binding requires an in
keyword to separate it
from the following expression in verbose mode.
λ dotnet fsi main.fsx Sum: 7, Product: 12
Loops in verbose syntax
Loop constructs require additional keywords in verbose mode.
let printNumbers n = let mutable i = 1 while i <= n do printf "%d " i i <- i + 1 done printfn "" printNumbers 5
This example demonstrates a while loop with verbose syntax requirements.
while i <= n do printf "%d " i i <- i + 1 done
The done
keyword is required to mark the end of the loop body in
verbose syntax.
λ dotnet fsi main.fsx 1 2 3 4 5
Type definitions
Verbose syntax affects how types are defined and implemented.
type Shape = | Circle of radius: float | Rectangle of width: float * height: float with member this.Area = match this with | Circle r -> System.Math.PI * r * r | Rectangle (w, h) -> w * h end let circle = Circle(5.0) let rect = Rectangle(4.0, 6.0) printfn "Circle area: %.2f" circle.Area printfn "Rectangle area: %.2f" rect.Area
This shows type definitions with verbose syntax markers.
with member this.Area = match this with | Circle r -> System.Math.PI * r * r | Rectangle (w, h) -> w * h end
The with
and end
keywords explicitly delimit the
member definitions.
λ dotnet fsi main.fsx Circle area: 78.54 Rectangle area: 24.00
Module definitions
Modules in verbose syntax require explicit begin
/end
markers.
module MathOperations = begin let add x y = x + y let subtract x y = x - y end printfn "Addition: %d" (MathOperations.add 10 5) printfn "Subtraction: %d" (MathOperations.subtract 10 5)
This demonstrates module definition with verbose syntax requirements.
module MathOperations = begin let add x y = x + y let subtract x y = x - y end
The begin
and end
keywords explicitly delimit the
module contents.
λ dotnet fsi main.fsx Addition: 15 Subtraction: 5
Implementing Interfaces with Verbose Syntax
When implementing interfaces, verbose syntax provides a structured way to define members. This is particularly useful when the interface has multiple members or when the implementation requires clarity in complex scenarios.
type IDisplayer = abstract member Display : string -> unit type ConsoleDisplayer() = interface IDisplayer with begin member this.Display msg = begin printfn "Message: %s" msg end end let displayer = ConsoleDisplayer() :> IDisplayer displayer.Display "Hello from verbose syntax"
The interface implementation is enclosed within a
begin
/end
block. The member implementation for
Display
is also wrapped in begin
/end
.
λ dotnet fsi main.fsx Message: Hello from verbose syntax