[bitc-dev] Moose, rugs, and separate compilation
naasking at higherlogics.com
Fri Mar 6 14:54:08 EST 2009
Jonathan S. Shapiro wrote:
> So the problem in the large is separate compilation, in the sense of
> "separated by an air gap". If we want to support modules written by
> truly unrelated development groups, we need a way to survive colliding
> instances. The only way that I can really see to do that is by using
> lexical scoping, but lexical scoping in the presence of polymorphism
> is a very strange thing.
> The issue is that you have a call to f() that in turn calls g() in
> some other module. Both modules have an instance in scope for (EXAMPLE
> (list char)), but they are not the same instance.
> The question is: which instance should be used in the compilation of
> g()? That is: which lexical environment should be used to decide what
> instance to use? There is truly no right answer to this.
Let's suppose we're dealing with an Eq 'a type class. Suppose f knows
the concrete type of the list it's dealing with, list char. Suppose that
g does not, and handles list 'a.
I would expect the answer is to transitively use whatever instance f
specifies. In other words, the beginning of the call chain where the
type class is first required dominates. I think of type classes as
abstracting vtables, so f is the one building the vtable being passed to
g, so g should be slaved to f.
typeclass Eq 'a with
eq: 'a -> 'a -> bool
val f: list char -> bool
val g: Eq 'a => list 'a -> 'a bool
(* f builds the vtable passed to g, so the "Eq char" instance
* in f's scope would seem to be the most straightforward answer.
let f list = g list '\n'
To be consistent, I think the same reasoning should apply if both f and
g are monomorphic. g is accepting an Eq char from f, so f should specify
the behaviour of Eq char. Hopefully I'm not missing anything obvious.
More information about the bitc-dev