I created a generic class MyClass<T: Numeric> {...} and got errors in my functions that tried to use > and <, along the lines of "Binary operator '>' cannot be applied to two 'T' operands." I spent quite a while thinking that the problem was some syntax error I had made in the declaration. But sure enough, Numeric doesn't inherit from Comparable. I am stunned. Why would this be?

  • 3
    Because there are numbers that aren't Comparable? – Jörg W Mittag Aug 31 '17 at 18:29
  • @JörgWMittag Do you mean that there are actual number types that aren't comparable, or do you mean that the Swift designers felt that it would be good not to force users of a Numeric protocol into implementing comparison operators? If the former, do you have any examples? If the latter, then I guess I'm still wondering why. If you downvoted me, perhaps because you felt that the answer was obvious, please allow me to point out that I don't know what your answer means, so perhaps the answer to my original question is not as obvious as you may think it is. – SaganRitual Aug 31 '17 at 18:44
  • 6
    Complex numbers and vectors and matrices would be examples of “numeric” concepts that don't have a total order. Note that Numeric also doesn't include division, which is undefined for many mathematical entities. By not including these concepts, Numeric is more general. Compare also the interface segregation principle: don't depend on methods you don't use. – amon Aug 31 '17 at 18:49
  • @amon Thank you so much. I hadn't noticed that Numeric didn't include division. If I had, it might have given me a clue to answer my own question (and the answer would be that the Numeric protocol is mis-named). If you'd like to post your comment as an answer, I'll mark it as accepted. Thanks again. – SaganRitual Aug 31 '17 at 18:55

There is a notable numeric type that is not comparable: complex numbers.

Complex numbers consist of a “real” and “imaginary” part, or equivalently a “magnitude” and “phase”. There is no obvious order to imaginary numbers. By not including Comparable, the Numeric protocol could also be used to represent complex numbers.

Note that Numeric also doesn't include division. I am not sure why this was excluded, but note that division is only partially defined for integers, e.g. 3/2 does not produce an integer value. Different languages tackle this differently (C rounds to zero, sensible languages produce floating point numbers, Perl6 produces rational numbers, …). It therefore seems legitimate to exclude these decisions from a very fundamental protocol like Numeric rather than forcing implementing types to make a decision.

(More formally: common numeric types are closed under addition and multiplication. Unsigned types with underflow (i.e. modular arithmetic) and signed types are also closed under subtraction. Integers are not closed under division. Closure means that the output type of an operation is the same as the input type.)

While Numeric is focussed on scalar values, there are many examples of (non-scalar) mathematical constructs that have no order and no division either. Notably, vectors and matrices.

Protocols should be as minimal as they can be while still being useful. They should not constrain types unnecessary. Compare also the SOLID principles: the Interface Segregation Principle (ISP) states that users should not be forced to depend on methods they don't use.

  • As you pointed out, integers are not closed over division (i.e. dividing two integers can result in a non-integer), so it seems appropriate that an associatedtype could be defined which species the result of division. But then that makes it hard to have both integer (rounding) and floating point division, and muddies stuff way too much – Alexander - Reinstate Monica Dec 2 '17 at 21:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.