For example, the following program is type correct because polymorphic equality is applied to variables of type ''a.
fun f (x: ''a, y: ''a): bool = x = y
On the other hand, the following program is not type correct, because polymorphic equality is applied to variables of type 'a, which is not an equality type.
fun f (x: 'a, y: 'a): bool = x = y
MLton reports the following error, indicating that polymorphic equality expects equality types, but didn't get them.
Error: z.sml 1.32. Function applied to incorrect argument. expects: [<equality>] * [<equality>] but got: [<non-equality>] * [<non-equality>] in: = (x, y)
As an example of using such a function that requires equality types, suppose that f has polymorphic type ''a -> unit. Then, f 13 is type correct because int is an equality type. On the other hand, f 13.0 and f (fn x => x) are not type correct, because real and arrow types are not equality types. We can test these facts with the following short programs. First, we verify that such an f can be applied to integers.
functor Ok (val f: ''a -> unit): sig end = struct val () = f 13 val () = f 14 end
We can do better, and verify that such an f can be applied to any integer.
functor Ok (val f: ''a -> unit): sig end = struct fun g (x: int) = f x end
Even better, we don't need to introduce a dummy function name; we can use a type constraint.
functor Ok (val f: ''a -> unit): sig end = struct val _ = f: int -> unit end
Even better, we can use a signature constraint.
functor Ok (S: sig val f: ''a -> unit end): sig val f: int -> unit end = S
This functor concisely verifies that a function of polymorphic type ''a -> unit can be safely used as a function of type int -> unit.
As above, we can verify that such an f can not be used at non equality types.
functor Bad (S: sig val f: ''a -> unit end): sig val f: real -> unit end = S
functor Bad (S: sig val f: ''a -> unit end): sig val f: ('a -> 'a) -> unit end = S
For each of these programs, MLton reports the following error.
Error: z.sml 2.4. Variable type in structure disagrees with signature. variable: f structure: [<equality>] -> _ signature: [<non-equality>] -> _
Equality type variables in type and datatype declarations
Equality type variables can be used in type and datatype declarations; however they play no special role. For example,
type 'a t = 'a * int
is completely identical to
type ''a t = ''a * int
In particular, such a definition does not require that t only be applied to equality types.
Similarly,
datatype 'a t = A | B of 'a
is completely identical to
datatype ''a t = A | B of ''a