Pattern matching is F#’s idiomatic conditional-logic tool. A match tests a value against ordered patterns and evaluates the handler for the first match. Because it is an expression, every branch returns the same type and the whole match produces a value. section 8.1 section 8.5
Listing 8.1 Basic pattern matching
let value = System.ConsoleModifiers.Alt
let description =
match value with #1
| System.ConsoleModifiers.Alt -> "Alt was pressed." #2
| System.ConsoleModifiers.Control -> "You hit control!" #2
| System.ConsoleModifiers.Shift -> "Shift held down..." #2
| _ -> "Some modifier was pressed" #3
This basic match turns a console modifier into a description. `match`, `|`, and `->` replace switch/case syntax; `_` handles values not covered by earlier patterns. section 8.1 section 8.1.1
Order matters: a broad pattern placed first can make later rules unreachable. The compiler warns when cases are missing or overlap. Treat missing cases seriously: an unmatched value causes a runtime exception, while an explicit fallback can return an error or throw a purposeful exception. Wildcards are useful for open-ended values such as .NET enums, but can hide future cases. section 8.1.1 section 8.3.4
Use patterns to make branching reflect the shape of the data:
- Match constants, tuples, and records when a decision depends on particular values. Record patterns can name only the fields relevant to each rule, improving readability over positional tuples. section 8.1.3 section 8.1.4
- Match lists to recognize empty input, exact list shapes, or a head and remaining items without unsafe indexing. section 8.2.4
- Match discriminated unions to select a case and safely bind only that case’s contained data. section 8.3.2 section 8.3.4
- Prefer `if/then/else` for direct Boolean tests and concise unit-returning side effects; use a match when the alternatives are structural cases. section 8.2.5
Refining a loan decision
A loan rule can begin as several tuple cases, then combine alternatives with the same result: reject `(0, _)` and `(1, true)`, accepting everything else. Replacing raw integers and Booleans with discriminated-union cases such as `OneYear` and `Overdrawn` makes the rule readable and total, so every modeled case is explicit. section 8.1.3 section 8.3.4
Pattern matching also safely consumes optional and result-like domain values. An option must be matched as `Some` or `None` before its content is used; matching results can similarly choose behavior by success or error. Exhaustive union matches reduce the need for tests that merely check whether every case was handled, though tests still verify that each handler gives the correct outcome. section 9.1.2 section 9.2.6 section 14.1.1











