Module C2.01
From classes to modules & functions
A C# developer's first question is where a method goes. F# answers it differently.
In C#, behaviour lives in classes — a method on a type, called through an
instance or a static reference. F# keeps the two jobs apart: data lives in records and
unions, and behaviour lives in modules as let-bound
functions. A module is the unit a static class was; a function
is what a method was — but the instance is now an ordinary argument, not a hidden this.
This module makes that move concrete in three dives: a C# static class of helpers becoming an F# module, an
instance method becoming a function over a record, and the organisational rules a C# developer meets on day one
— namespaces, type members, and the one that surprises everyone: declaration and file order is
significant.
Where behaviour goes
The translation has one organising idea, and the rest follows from it. In C#, a class binds data and the
methods that act on it into one declaration. In F#, those are two separate things: a record
holds the data, and a module holds the functions. The function takes the record as its first
argument instead of receiving it implicitly as this.
Read the move once and it recurs everywhere. A static class of stateless helpers
— the most direct case — becomes a module of functions, with no public static
ceremony to write. An instance method that reads and updates fields becomes a function that takes the record
and returns a new one. And because F# files are read top to bottom with no forward
references, the order you write declarations in is part of the program, not a stylistic choice.
The three dives · select one
A C# static class of helpers becomes an F# module of let-bound functions. Top-level functions need no class to hang on, and there is no public static ceremony.
Open this dive · or pick another above
Data in records, behaviour in modules, the instance passed as an argument. Hold that one substitution and every C# class on this page translates.
The three dives
Read them in order. Each shows the C# a reader already knows beside the idiomatic
F#, then names the shift. Every F# line below runs in dotnet fsi and
prints exactly what the page shows; every C# line is valid, idiomatic C#.
Static classes → modules
A C# static class of helpers becomes an F# module of functions — open to bring names in, no public static.
- modulethe namespace + static-class unit, as one keyword
Instance methods → functions
An instance method becomes a function over a record; a "mutating" call returns a new record, leaving the original untouched.
- recordno
this— the instance is an argument
Namespaces, members & file order
Namespaces vs modules, [<AutoOpen>], let private, type members for dot-syntax — and the surprise: file order is significant.
- ordertop-down, no forward references
References
Sources
- Microsoft — F# documentation — modules, namespaces, members, and access control.
- Microsoft — F# modules — the language reference for
module,open, and[<AutoOpen>]. - The F# Language Specification — namespaces, modules, and the significance of declaration order.
Related in this course
- C2.01.1 — Static classes → modules — the first and most direct translation.
- C2 — F# for C# developers — the chapter this module opens.
- C1.03 — Functions — the
let-bound functions a module is filled with. - Elixir — Functional core — the same split: functions in modules, data passed in.