[MLton-user] bug report: vector equality

Stephen Weeks sweeks@sweeks.com
Thu, 26 Feb 2004 17:46:29 -0800


Hi Sam.  Thanks for the bug report.

> The latest experimental release of mlton (20040221), and the previous one
> from the beginning of January both fall over on the following code:
> 
>   val _ =
>     if (Int32Vector.fromList [1])=(Int32Vector.fromList [2]) then
>       TextIO.print "oops"
>     else
>       TextIO.print "not equal"
> 
> $ mlton test.sml
> Error: test.sml 2.32: function applied to incorrect argument
>    expects: [<equality>] * [<equality>]
>    but got: [<non-equality>] * [<non-equality>]
>    in: = (Int32Vector.fromList [1], Int32Vector.fromList [2])
> compilation aborted: elaborate reported errors
> 
> It compiles correctly under the release version.

Under my reading of the basis library specification, the behavior of
MLton 20040221 is correct.  There is a difference between the types
"Int32.int vector" and "Int32Vector.vector".  The former is an
equality type, because the vector type admits equality, as can be seen
in the VECTOR signature, which says "eqtype 'a vector".  The latter is
not an equality type, as can be seen in the MONO_VECTOR signature,
which says "type vector", not "eqtype vector".

The difference in equality is admittedly a bit confusing, but I don't
know of a better way to specify things.  The MONO_VECTOR signature can
not be changed to say "eqtype vector", because some mono vectors are
not eqtypes, e.g. RealVector.

> For some reason mlton is failing to infer that vectors of equality
> type are themselves equality types.

I think MLton does this OK.  The lack of equality in Int32Vector (and
other mono vectors) is because the basis library constrains
Int32Vector to abstractly match the MONO_VECTOR signature, and hence
hide the fact that the underlying type is an equality type.

> Equality on CharVectors works fine, but then they use strings as the
> underlying representation type, so that's not terribly surprising.

Right, CharVector.vector is a special case in the basis library spec
and in the MLton code, because it is where-typed to be the same as
string, which is an equality type.

> There's an easy workaround, which I successfully used - simply map
> vectors back to lists, and lists of equality type are equality
> comparable.

You can compare mono vectors directly as follows.

----------------------------------------------------------------------
functor Equals (structure V: MONO_VECTOR
		val elemEquals: V.elem * V.elem -> bool):
   sig
      include MONO_VECTOR
	 
      val equals: vector * vector -> bool
   end =
   struct
      open V
	 
      fun equals (v: vector, v': vector): bool =
	 length v = length v'
	 andalso not (isSome
		      (findi (fn (i, x) => not (elemEquals (x, sub (v', i)))) v))
   end
----------------------------------------------------------------------