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