So, in your example, the operation '+' isn't defined for the value "dog". However, let's say we had the operation '_' (string concatenation). It would be defined for "dog" ... it could also be defined for "3.14". So, the statement 3.14 _ "dog" could have meaning ... right?
Yes, that could have meaning. If you're the person designing the type system, you get to decide which statements have meaning. So you weigh the trade-offs. On the one hand, allowing the use of '+' in a statement like
3.14 + "dog" has the advantage of being short and sweet; easy for the programmer to type, and it reduces the number of operators/functions he has to learn. And if the programmer has a question about the semantics, he can look it up in the manual. On the other hand, you ask if it is really so much trouble to break that operator into two separate ones:
stringify(3.14) + "dog" or
3.14 + numify("dog") . Now the programmer is forced to make his intentions explicit in the code, rather than implicit (i.e. in the documentation). Is one method better/faster/cleaner/buggier than the other? You get to decide (but be forewarned, that's the stuff of holy wars).
-- All code is 100% tested and functional unless otherwise noted.