I’ve frequently wondered this myself, and to my best understanding, the reason these don’t exist is rather because they would be so fundamentally important! Such traits would be life-changing if they existed, so the bar is understandably set high.
(In fact, if you peek waaaaaaay back in time you’ll find that traits like these used to exist!)
While I’ve no direct knowledge of the history of these traits, part of the trouble with stuff like that is that they invite a significant amount of hierarchy-building, and nobody can agree on how the pieces should fit together. If they’re too small and general, then they’re almost certainly not useful (Iterator is the exception, not the rule!); if they’re too specific, then it won’t take long for somebody to come along with a type that just barely doesn’t fit in.
When I code in Haskell, there isn’t a day that I don’t curse at their Num trait. This one trait provides all of: the binary
(-) operators, unary negation,
fromInteger (used for pattern matching, an extremely fundamental feature).
It was only in May of last year that Haskell’s standard library finally got an unsigned bigint type (Natural) to go along with the signed bigints (Integer) it has had since the dark ages. Needless to say,
negate is defined to throw an exception.
Rust on the other hand did away with its Num trait before 1.0 (I think). No cursing from me. (well, maybe less cursing)