[mercury-users] ambiguous overloading causes type ambiguity.

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Apr 30 21:01:55 AEST 2001


On 29-Apr-2001, Terrence Brannon <princepawn at earthlink.net> wrote:
> 
> [localhost:mercury/primality/divisors] metaperl% mmc -E --infer-all divisors.m
> divisors.m:010: In clause for predicate `divisors:main/2':
> divisors.m:010:   error: ambiguous overloading causes type ambiguity.
> divisors.m:010:   Possible type assignments include:
> divisors.m:010: V_15 :: string or (pred string)
> 	You will need to add an explicit type qualification to resolve the
> 	type ambiguity.
> 	The way to add an explicit type qualification
> 	is to insert a call to a dummy predicate whose `:- pred'
> 	declaration specifies the appropriate argument types.

The error message is in fact out-dated; in Mercury 0.10,
we added syntactic support for explicit type qualification,
using the syntax

	Expression `with_type` Type

The error message is also not very helpful in locating the error;
the line number is just the first line of the clause in which the
error occurs, and unfortunately the variable whose type is
ambiguous is an unnamed one that was introduced by the compiler.

It would be nicer if the compiler issued better error messages.
Of course, this is easier said than done ;-)  I've fixed it
to recommend using "with_type" rather than a dummy predicate.
But getting it to report the location of the error more accurately is
not so easy.

In the mean time, there are several things you can do to help
debug type errors like this.  To get more information about the type
inference process, you can run the compiler with the `--debug-types' and
`--very-verbose' options.  (In this particular case, that is probably not
very helpful, but it can be useful in other cases.)  To figure out which
expression an unnamed variable like `V_15' corresponds to, you can use
the options `-d all -D all', which will produce a series of files named

	divisors.hlds-dump.01-initial
	divisors.hlds-dump.02-typeclass
	divisors.hlds-dump.03-typecheck
	divisors.hlds-dump.04-puritycheck
	...

that contain a human-readable dump of the compiler's intermediate
representations.  If you look at the first of these, and search for the
clauses for the predicate involved (in this case `main'), you'll find
something like this:

	divisors:main(HeadVar__1_1, HeadVar__2_2) :-
		HeadVar__1_1 = DCG_0_7,
		HeadVar__2_2 = DCG_6_13,
		io:read_line_as_string(W0_3, DCG_0_7, DCG_1_8),
		( % disjunction
			W0_3 = eof,
			V_16 = "Nothing could be read",
			print(V_16, DCG_1_8, DCG_2_9),
			nl(DCG_2_9, DCG_6_13)
		;
			W0_3 = error(Err_4),
here ======> 		V_15 = io:error_message(Err_4),		<====== here
here ======>		print(V_15, DCG_1_8, DCG_4_11),		<====== here
			nl(DCG_4_11, DCG_6_13)
		;
			W0_3 = ok(W_5),
			I_6 = string:det_to_int(W_5),
			V_14 = test(I_6),
			io:write_string(V_14, DCG_1_8, DCG_6_13)
		).

As you can see from the lines that I've marked, `V_15' corresponds
to the expression `io__error_message(Err_4)', which is the first
argument in the call to `print'.  Now, according to the compiler
error message, this has an overloaded type; it could be either
`string' or `(pred string)'.  How does that occur?  Well, there's
two declarations for `io__error_message' in the standard library:

	:- func io__error_message(io__error) = string.

	:- pred io__error_message(io__error, string).
	:- mode io__error_message(in, out) is det.

An expression such as `io__error_message(Err_4)' could mean two
things: it could either be a call to the function `io__error_message/1',
in which case the result will be a string, or it call be a partially-applied
call to the predicate `io__error_message/2', in which case the result
will be a higher-order term equivalent to

	(pred(X::out) is det :- io__error_message(Err_4, X))

whose type is `pred(string)'.  Since the only thing you do with this
term is to pass it to the polymorphic routine `io__print', the compiler
doesn't know whether you are trying to print out a string or to print
out a higher-order term.

The solution is to give the compiler more information.
You can either use `with_type' to give an explicit type annotation,

 	print(io__error_message(Err) `with_type` string), nl
				     ^^^^^^^^^^^^^^^^^^

or you can use io__write_string instead of io__print

 	write_string(io__error_message(Err)), nl

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list