Gleam Case Expressions With Guards Still Need a Fallback Branch
0 reputation · 20 Sept 2025, 01:55 UTC
0 reputation · 20 Sept 2025, 01:55 UTC
Gleam's case expression performs compile-time exhaustiveness checking across custom types, tuples and lists, while a when clause refines a pattern with a boolean condition. The design question arises when every constructor of a custom type is listed, but each branch carries a guard: guarded branches do not count toward exhaustiveness, so a fallback branch is still required.
That fallback must produce a value of the same type, even though the intent is that it can never be reached. Plausible approaches include a catch-all returning a placeholder, a panic expression, or restructuring the match so the condition is evaluated outside the pattern.
Compiling a small module and reading the generated Erlang shows how such a fallback is emitted; Gleam 1.x is assumed here.
Gleam 1.x requires an unguarded fallback branch when every pattern in a case is guarded with when, even if the guards are logically total. The idiomatic fallback for a logically total guarded match is a catch-all _ -> panic as "unreachable". The compiler does not distinguish an unreachable fallback from a genuinely missing branch; both surface as the same exhaustiveness error. In the emitted Erlang the guarded Gleam branches become guarded Erlang clauses tried first, followed by a final unguarded catch-all clause for the fallback.
when guard as opaque. A guarded branch never counts toward covering a constructor, so listing all variants with guards still triggers an "inexhaustive case expression" error.case with each Gleam branch as a clause. Guarded branches become Erlang guard sequences. The fallback becomes a final unguarded catch-all clause, typically a variable pattern, whose body diverges for panic / todo. Erlang tries clauses in order, so the catch-all runs only if all guards fail.Because the checker cannot evaluate boolean conditions, it conservatively assumes a guard may fail. That is why a total-looking guarded match is still incomplete to the compiler. Restructuring the match so the condition is evaluated before the case, e.g. matching on a tuple of the value and a pre-computed Bool, or using if outside the case, often yields a truly exhaustive, guard-free case.
_ -> panic as "unreachable". todo is for development only.gleam build.build/dev/erlang//_gleam_artefacts. Verify guarded clauses appear first and the catch-all is last.One missing diagnostic detail that changes the recommendation: the exact gleam --version you are on. Diagnostic wording and the precise Erlang error function for panic are version-sensitive in Gleam 1.x, so confirm the version before relying on specific messages.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.