[mercury-users] Typeclass problem (bug, misunderstanding, oth er?)

Ralph Becket rbeck at microsoft.com
Thu Aug 3 00:41:34 AEST 2000


> From: Fergus Henderson [mailto:fjh at cs.mu.OZ.AU]
> 
> Well, if you get an error that you can't understand, the first
> step should be following the compiler's suggestion: try recompiling
> with `-E'.  That will give you a little bit more information:

Sorry - brain failure.

> 
>         The body of the clause contains a call to a 
> polymorphic predicate,
>         but I can't determine which version should be called,
>         because the type variables listed above didn't get bound.
>         (I ought to tell you which call caused the problem, 
> but I'm afraid
>         you'll have to work it out yourself.  My apologies.)
> 
> This error happens when you do something like this:
> 
> 	main -->
> 		io__read(X),
> 		io__write(X).
> 
> Here the compiler has no idea what type `X' should have.
> You need to specify the type explicitly, e.g. via
> 
> 	main -->
> 		{ qualify_type(X) },
> 		io__read(X),
> 		io__write(X).
> 
> 	:- pred qualify_type(io__result(int)::unused) is det.
> 	qualify_type(_).   % ^^^^^^^^^^^^^^^

This point is sufficiently subtle that I think some explanation
should be provided in the reference manual.

The point is that while the compiler can assign a *typeclass*
to the offending variables in

>          pop_stack(PoppedNodes),
>          push_agenda(PoppedNodes),
> 
>          pop_agenda(CFn, NewTop),
>          push_stack(CFn, NewTop),

it can't work out a *type*.  In this case, it shouldn't actually
matter what the type of PoppedNodes or NewTop turns out to be to
the code in question.

> Perhaps the solution in this case may be to use existential types
> for the `pop' methods, e.g.
> 
>      some [N]
>      pred pop_stack(list(N), T, T) => node(N),
>      mode pop_stack(out, in, out) is det,
> 
> This declaration would mean that the `pop_stack' method, rather
> than its caller (solve/4), is responsible for binding the type
> variable N.  That would make sense if your stacks are heterogenous
> stacks (i.e. each stack can contain lists of several different types).
> 
> If your stacks are supposed to be homogeneous stacks, then probably
> the right thing to do is to use a multi-parameter type class,
> making `N' a type class parameter.

My stacks are homogeneous, so I'll try using a multi-parameter
typeclass (this is what I did in the first place, but ran into
problems which I come to next...)

In your reply to my other typeclass help request, you suggest adding
a dummy parameter to the function in question:

	:- func solve(CSP, Node) = CSP <= csp(CSP, Node).
	:- mode solve(in, unused) = out is det.

	...
	main -->
		{ node_type(DummyNode) },
		{ Sol = solve(CSP, DummyNode) },
		...

	% this predicate just constrains the type of its
	% argument to be `int'
	:- pred node_type(my_node::unused) is det.
	node_type(_).

While this will work, it does seem to be something of a hack.  I
wonder if there's some small addition we could make to the language
that would handle this more gracefully?  E.g.

:- func solve(CSP) = CSP <= (some [Node] csp(CSP, Node)).

solve(CSP0) = CSP :-
	some [PoppedNodes, TopNode] (
		... code in which it would otherwise be
		... impossible to work out a type for
		... PoppedNodes and TopNode, but which
		... doesn't need to know
	).

Ralph
--------------------------------------------------------------------------
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