Earlier quoted context omitted.
> How can you "Make illegal states unrepresentable" with mutable state By either making the data const, or encapsulating mutable state with private fields and public methods > How can you do "Errors as values" Go, Rust, Odin, Zig, and many more are imperative languages that do exactly this > How can you do "Functional core, imperative shell" Write a function that takes the old state and returns the new state
> By either marking your data as const, or encapsulating mutations with private fields and public methods That would seem to be making illegal states unreachable rather than unrepresentable, closer in spirit to "parse, don't verify".
For modeling the data in the first place, just use the right combination of sum types, product types, and newtypes - that's not specific to functional languages. I'm sure GP knew this already without me saying it. Sum types may have been a "functional programming" thing a few decades ago but they aren't anymore.