2
votes

When defining a simple function that takes the square of a value, SML NJ infers the signature for this function to integer types. When declaring the signature for float types, SML can work with floating point values here.

- fun sqr x = x * x;
val sqr = fn : int -> int
- fun sqqr (x : real) = x * x;
val sqqr = fn : real -> real
- sqqr 3.4;
val it = 11.56 : real
  • Why and how does SML infer this specific type here?
  • Is there a specific preference for ints?
  • Is this special behaviour for these arithmetic operations or can it be found in other places?
2

2 Answers

5
votes

SML's approach to types really doesn't work very well with overloading, which is why you can't define your own overloaded functions. But -- the overloading of arithmetical and relational operators is so widespread in programming languages that the designers of SML accepted the standard overloading of +, * etc. This presented a problem with SML's type inference mechanism. To solve it they could have required explicit type declarations in such cases, but this would have decreased the usefulness of type inference. Instead, they latched onto the idea of picking a default type for functions which have the property that their definition makes perfect sense for both ints and reals (or even strings if it involves < or >), together with a mechanism for overriding the default. Given that the main applications of SML are in things like automatic theorem provers rather than numerical analysis, int seems like the natural choice. I have probably accepted the default 10 times for every time that I've needed to override it.

2
votes

The SML 97 specification defines the behavior of overloaded operators in Appendix E. For *,+,- the default type is int. For / the default type is real. This helps maintain the "Standard" in in "Standard ML."