In connection with the current debate about modules and classes, I will
describe the view we are trying to develop in Brisk, and then describe how
this gives a slightly different perspective on the global instance property at
the end.
We are trying to develop a meaning for overloading, including the import and
export of instances of an overloaded function, which is independent of classes
and class instances. We regard classes as a mechanism for type checking only,
ie for ensuring that an overloaded function is never applied at run time to a
value of a type at which it has no instance.
When an overloaded function f is first defined (in a class declaration), it is
regarded as a function which can be applied to values of any suitable type
*including* types which haven't been invented yet (as is the case with
polymorphic functions). The function f has a single meaning everywhere it is
used (or at least a single meaning per Main program module). I agree with
Phil that this meaning must be independent of type declarations, so in
particular:
g :: C a => a -> a
g n = f (f n)
must have the same meaning as
g :: Int -> Int
g n = f (f n)
To be more precise, the second version will result in more programs being
rejected by the type checker, but the meanings of any programs which succeed
will be the same in the two cases. More generally, the meaning of a function
like g is independent of whether or not the compiler can determine which
instance to use, ie whether or not its type gets a class context (determining
the instance is just an inlining optimisation).
This brings us back to the global instance property. The single global
meaning of an overloaded function is determined by the instances which get
imported into the Main program module. Then Phil's question arises: can any
meaning be given to functions which get imported into Main, but which use
instances which don't get imported? My answer would be `no'. In Phil's
example, I would say that trouble uses difficult, and it is obviously the
intention of the programmer that the version of difficult used should include
the instance defined in module Two. Thus that instance travels with trouble
into module Three, *regardless* of any type declaration given to trouble, and
conflicts with the instance defined there, making the example illegal.
What I am suggesting is that, if you want a semantically correct automatic
rule for passing instances around, it should ensure the following. Whenever
you import a function g whose definition depends on an overloaded function f,
then any instances of f which were in scope in the module in which g was
defined should be imported along with it.
I believe Haskell current rules do ensure this, but are not liberal enough.
Ian [EMAIL PROTECTED], Tel: 0272 303334