Ch.8 SML# feature:other type system extensions

§ 8.3. First-class overloading

In ML, some of commonly used primitives are overloaded. For example, binary addition + can be used on several types included int, real, word as shown below.

1 + 1;
val it = 2 : int
1.0 + 1.0;
val it = 2.0 : real
0w1 + 0w1;
val it = 0wx2 : word

Different from polymorphic functions, a different implementation for + (i.e. one of Int.+, Real.+, Word.+ in the above example)is selected based on the context in which it is used. In Standard ML this overloading is resolved at the top-level at the end of each compilation unit. If there remain multiple possibilities then a predetermine one is selected. For example, if you write

fun plus x = x + x

in Standard ML, then Int.+ is selected for + and plus is bound to a function of type int -> int.

This strategy works fine, but this will become a big obstacle in integrating SQL, where most of the primitives are overloaded. If we determine the types of all the primitives in a SQL query at the time of is definition, then we cannot make full use of ML polymorphism in dealing with databases. For this reason, SML# introduces a mechanism to treat overloaded primitive functions as first-class functions. For explain, SML# infers the following polymorphic type for plus.

fun plus x = x + x;
val plus = fn
  : ['a::int, IntInf.int, real, Real32.real, word, Word8.word. 'a -> 'a]

This function can be used as a function of any type obtained by replacing 'a with one of int, IntInf.int, real, Real32.real, word, Word8.word. The constraint 'a::{...} on type variable 'a indicates the set of allowable instance types.