> those aren't integers, they are equivalence classes of integers.
And they form a ring and sometimes even a field. That's the least messy behavior of any arithmetic type usually implemented on a computer. The only messy part is division, which doesn't match modular division, but it's what you actually want, usually.
Most of the design problems around arithmetic types in programming languages are a result of people "wanting integers" (or "real numbers") rather than facing the reality of the machines they're programming for.
> trap on overflow, like Ada is supposed to do though it is usually shut off by a pragma
Sounds like people "usually" opt for "messy" behavior.
> For example, in Ada, if you want modular arithmetic, just specify it in the variable declaration. That is the right way to do it.
No disagreement there. Unfortunately, almost all non-niche programming languages get arithmetic wrong, ironically, because they're supposed to be the simplest types.
You have to choose from a range of possible behaviors that all have their use cases, and you have to be aware of the limitations of the actual type you're working with, which is not an integer but something finite. The language cannot make that choice for use. What the default is almost doesn't matter because choosing a particular behavior should be clear and simple.