On Thursday, February 17, 2000 7:02 PM, Fergus Henderson 
[SMTP:[EMAIL PROTECTED]] wrote:
>>
> Well, I remain unconvinced.  In Mercury, we give the user control
> over whether instance declarations are exported or not, and it
> works quite nicely, IMHO.  I think the problems that you are referring
> to below are only problems if in addition to allowing private instance
> declarations you also allow multiple or overlapping instance 
declarations.
> But I would assign the blame for these problems to multiple/overlapping
> instance declarations, not to having control of when instance
> declarations are exported.

I don't think this is the case. Suppose there is the present Haskell rule - 
only one C-T instance per program - with the addition that local "private" 
instances may be declared, which shadow the global instance in that module. 
This is a simple case, but allowing different  C-T instances in different 
parts of the program provided only one is visible in any scope would  not 
change the argument. Here is an example - I'll use a standard Class and 
Type to so I can use common sybols:

Suppose the normal Prelude instance decl for  type Integer as an instance 
of Num is shadowed in Module A by a private Num-Integer instance decl. 
Module A defines and exports a function

f::Integer->Integer->Integer
f x y = x*x+y*y

>
> > Consider a function, which is exported, and which uses a local 
"private"
> > instance decl. What happens in the importing module?
> > There are several possibilities:
> > 1. The "private" instance decl from the other module is used.
>
> That is what happens in Mercury.

OK, let's go with that option.

>
> > Then referential transparency is lost,
>
> No necessarily...
>
> > because if the name of the imported
> > function is replaced by its definition, any need for the instance will 
not
> > see the "private" instance declaration,
>
> Yes, but the result in Mercury will be a compile (or link) error.

Continuing the example:
Now Module B imports f from A. B has the normal Prelude  Num-Integer 
instance. If f brings with it the private instance - not as an import, but 
purely for its own use, -  any occurence in B of  f a b (a,b ::Integer) 
 will use it, (which you say happens in Mercury), but unfolding f a b to 
a*a+b*b, which referential transparency says should not change the result, 
will use the normal Prelude instance decl (and probably evaluate 
differently), because f is no longer referenced.

How can this produce a compile/link error? Are you saying that it is 
illegal in Mercury to import into a module using one C-T instance, a 
function which was declared in a module using a different C-T instance, 
even  if you don't import the instance, and the only place where it is used 
is in the imported function?

Note that if B doesn't import the Prelude instance, then unfolding f a b to 
a*a+b*b turns a valid program into an invalid one because * and + are 
undefined.

> > and if it finds another instance
> > decl in scope, will use that, and the semantics of the function will be 
> > changed.
>
> In Mercury there can't be another matching instance declaration
> in scope, since Mercury does not allow multiple or overlapping
> instance declarations.  Thus we preserve referential transparency.
>

In my example there is no place with multiple instances in scope. It's 
quite clear everywhere which instance is to be used, the problem is that 
normal semantics-preserving transformations break.

--brian

Reply via email to