Exhaustiveness checking is compiler verification that a pattern match covers every case a type can produce. It is especially useful with discriminated unions: when every union case is written explicitly, the compiler can confirm that no case was missed. A match over a free-form string cannot offer the same guarantee, because any other string may arrive. section 8.3.3
The practical benefit appears when a domain changes. If a ContactMethod union gains an Sms case, every match that has not handled Sms produces a warning. Adding the missing branch removes the warning, turning a potentially scattered maintenance task into a compiler-guided update. section 8.3.3
Match every case explicitly
A union for instruments can be matched without a fallback: type Instrument = | Guitar | Drums | Bass let play instrument = match instrument with | Guitar -> "Wah wah" | Drums -> "Ba dam tss" | Bass -> "Ba ba bom" Every Instrument value produces a string. If another Instrument case is added later, this match is no longer complete and the compiler can identify it. section 14.1.1
Coverage also descends through nested unions. An Sms contact method can contain either a Local or International TelephoneNumber. Matching only Sms (Local number) leaves International uncovered, and the warning names that missing nested shape rather than merely reporting a vague failure. section 8.3.4
Incomplete pattern matches on this expression. For example, the value 'Sms (_)' may indicate a case not covered by the pattern(s)
The diagnostic illustrates the feedback loop: adding a union case reveals a match that must be updated before its handling is complete. section 8.3.3
Use exhaustiveness as a design and maintenance aid:
- Model bounded domain states with union cases rather than broad values such as integers, Booleans, or strings when the possible states are known. section 8.3.4
- Prefer explicit branches when distinct cases may need different behavior later; a wildcard can silently absorb a newly added case. section 8.3.4 section 14.1.1
- Read warnings, or treat warnings as errors, so incomplete matches are acted on during development. section 14.1.1
- Still test the behavior chosen for each case when correctness depends on the result, such as associating the right instrument text with a case. section 14.1.1
A total match is not a claim that the chosen business result is correct; it only establishes that each representable case has a branch. Types and completeness checking can remove the need to test whether a union case was omitted, while tests remain useful for validation logic and for checking that each branch does the intended thing. section 8.3.4 section 14.1.1
