Search code examples
polymorphismsmltype-conversionabstract-data-type

A polymorphic addition function in SML without using datatype


I've made some progress in my learning of SML, trying to solidify my understanding of some of the most basic concepts. The following exercise proves that there is still much to be learned.

I'm asked to implement a function named add that receives two numbers and returns their sum. Problem is, add is supposed to receive a disjoint union of integers and real numbers, and return a disjoint union in the following manner: if both numbers received are integers, it should return the sum as an integer. Otherwise, if one of both of the arguments is real, the sum should be returned as a real number.

The most reasonable solution is to use datatype, yet I'm specifically instructed not to use it in any way, shape or form. To put it in other words, I should implement some sort of mechanism for determining the type of the parameters, and, as it follows, determining the return type.

All attempts were futile. Either SML infers that my parameters are of one specific type (which is not the case), or it demands the return value to be of a certain type, which is quite understandable but still frustrating. I've no idea how to overcome SML's typing restrictions. If it is of any use, I'm hinted to use tuples.


Solution

  • I'd really recommend reviewing the answer submitted by John Coleman, as this is the most reasonable way to approach it. However, my instructor had something different in mind. So for the sake of future generations, here's my primitive and utterly impractical implementation, which is what was expected:

    fun add (a, b, _, _, 0) = (a+b, 0.0)
      | add (_, b, x, _, 1) = (0, real(b) + x)
      | add (_, _, x, y, _) = (0, x + y);
    

    There is quite a resemblance to the C union data type. A tuple of 5 elements is used to send arguments to the function: 2 integer entries, 2 real entries and a tag which differentiates between the 3 possible ways of adding them (int/int, int/real, real/real). Again, this was written for educational purposes only, so for any practical use of this function please refer to John Coleman's answer.