[m-dev.] Foreign type compare and unification

Mark Brown dougl at cs.mu.OZ.AU
Tue May 21 16:10:22 AEST 2002

On 21-May-2002, Peter Schachte <schachte at cs.mu.OZ.AU> wrote:
> > Mark objected that this would be bad in that the behaviour of a program
> > could change if someone later added an explicit c(T') instance
> > declaration.
> True enough, but how much worse is that than the current state of
> affairs in which adding an instance declaration in some unrelated
> module in your application, or even just linking in a new library
> module, can cause your application not to compile (actually, link) at
> all?

The point is that if there is a bug, or if a programmer has overlooked
something in the source code, then it is much better for it to show up
at compile (or even link) time than to show up in the behaviour of the
program, where it could conceivably slip through testing and ultimately
affect the end user of the software.

What I'm saying is that the behaviour of the program should not depend on
a closed world assumption about the members of a typeclass.

However, this particular objection is not very hard to overcome.  Consider
the following motivating example, the intent of which should be clear.

	:- typeclass printable(T) where [
		func to_doc(T) = doc

It would be nice to provide a generic method implementation, along the
lines of the function pprint__to_doc in the standard library.  Perhaps
something like the following (note that, unlike ordinary instance
declarations, the parameter is a type variable):

	:- generic_instance printable(T) where [
		(to_doc(X) = pprint__to_doc(X))

This would _not_ imply that all types are members of the typeclass.  In
order to declare a type to be in the typeclass, we could use an ordinary
instance declaration, or we could use something like:

	:- derived_instance printable(foo).

This would use the generic method, binding the hidden type parameter to
the type_info for foo.

In our example, most types could get by with a derived instance, but types
which we want to print using special syntax (e.g. lists) would have an
ordinary instance.  If both an ordinary instance and a derived instance are
declared, this should be an error.

It turns out, though, that this proposal doesn't achieve what I hoped it
might.  I was hoping that it would be possible to write a generic method
which, like pprint__to_doc, deconstructs terms of any type and makes a
recursive call for each argument.  While this is fine for pprint__to_doc,
whose polymorphism is unconstrained, it won't work for our typeclass method
because the arguments would need to be dynamically cast into the printable
typeclass before the method can be called.  And there's the rub: if we had
dynamic typeclass casts, then we could implement this whole example without
using generic/derived instances at all.


mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au

More information about the developers mailing list