[mercury-users] Modules, Submodules and Instances.

Ralph Becket rwab1 at cam.sri.com
Mon Feb 1 22:49:02 AEDT 1999


Fergus Henderson wrote on  1 Feb:
> Fergus Henderson <fjh at cs.mu.oz.au> wrote:
> > Tyson Dowd <trd at cs.mu.OZ.AU> wrote:
> > > If you have an instance in module x:
> > > 	:- module x.
> > > 	:- instance foo(bar).
> > > 
> > > and bar is an abstract equivalence defined in the implementation of
> > > x:
> > > 	:- implementation.
> > > 	:- type bar == floobie.
> > > 
> > > then the compiler will create a base_typeclass_info__....foo_1__floobie_0
> > > declaration for the instance.
> > > 
> > > But in another module, y, that imports x, it will create references to
> > > base_typeclass_info__....foo_1__bar_0 which leads to a link error.
> > > 
> > > Workaround is to define bar as a no-tag type, e.g.
> > > 	:- type bar ---> bar(floobie).
> > 
> > 	1.  Disallow instance declarations for abstract equivalence types.

Oh God no!

> > 	2.  Disallow abstract equivalence types.

Oh God no!

> > 	3.  Allow instance declarations for abstract equivalence types.
> > 
> > 	    If we allow them, then we need to decide on the semantics.
> > 	    It's difficult to figure out a semantics that makes sense,
> > 	    doesn't lead to lots of overlapping instance declarations,
> > 	    and that is easy to implement.  Some seemingly simple
> > 	    approaches make cross-module optimization much harder.

Do the semantics get confused if we do the following?  Whenever the
compiler sees an abstract equivalence type with an instance
declaration, it silently turns it into a no-tag type by gensym'ing up
a constructor?  That is,

	:- interface.
	:-	type t.
	:-	instance foo(t).
	:- implementation.
	:-	type t == u.

Is detected and translated into

	:- interface.
	:-	type t.
	:-	instance foo(t).
	:- implementation.
	:-	type t == really_unique_constructor_name_123(u).

by the compiler which then puts in the extra bits of syntax wrapper
around all predicate/function arguments declared to be of type t, so

	:- pred p(t, ...).
	p(T0, ...) :-
		...,
		p(T, ...).

becomes

	:- pred p(t, ...).
	p(really_unique_constructor_name_123(T0), ...) :-
		...,
		p(really_unique_constructor_name_123(T), ...).

This would save source code from becoming needlessly messy.

> Hmm, thinking about it a bit more I see there is another possibility:
> 
>  	4.  Extend the language to support abstract instance declarations,
> 	    and allow abstract instance declarations for abstract
> 	    equivalence types, if those declarations occur in the interface
> 	    of the module defining the abstract equivalence type.
> 	    For an equivalence type `:- type foo == bar',
> 	    the instance definition for `foo' would implicitly be the same
> 	    as the instance definition for `bar' (and if there was no
> 	    instance definition for `bar' visible in the module's
> 	    implementation section, you should get a compile error).
> 
> 	    This approach means that equivalent types always have equivalent
> 	    instance definitions, so it avoids the problems that approach 3
> 	    has with overlapping instance definitions and cross-module
> 	    optimization. 
> 
> 	    On the other hand, it still has has most of the same drawbacks
> 	    as approach 1, because abstract instance declarations are not
> 	    first class.  <Sigh>.

Keeping abstract instances first class should be a priority.

-- 
Ralph Becket  |  rwab1 at cam.sri.com  |  http://www.cam.sri.com/people/becket.html



More information about the users mailing list