I disagree that there isn't a truly right answer to this question. IMO the right way to think about type classes is as defining theories: a set of symbols (both types and values) which have certain relationships. The view of type classes as some global relation on types is the wrong one. The only special role of types is in instance selection, and that can and should be a local lexical process. You absolutely should end up with different instances because of different local contexts, for example by picking a different comparison instance before invoking sort.
I'm not sure I understand your optimization concern. If you write code that's abstract, by making it depend on a number of type classes, then it will tend to be hard to optimize it in a separate-compilation setting. But if in compiling g you already have concrete types in mind, then the instance used for them should be decided lexically in g and will not be overriden by context later, right? Maybe you can provide an example of what you're worried about here? --- On Fri, 3/6/09, Jonathan S. Shapiro <[email protected]> wrote: From: Jonathan S. Shapiro <[email protected]> Subject: Re: [bitc-dev] Moose, rugs, and separate compilation To: "Discussions about the BitC language" <[email protected]> Date: Friday, March 6, 2009, 8:11 PM On Fri, Mar 6, 2009 at 2:54 PM, Sandro Magi <[email protected]> wrote: >> 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.... Yes. This was my initial thought as well. This is what I have described as the "lexical instance resolution" policy. And mostly I think that it's the right thing. One problem with it is that it makes pre-expanding things for dynamic libraries difficult, because we cannot anticipate the context from which the function will later be called at the time we are compiling the library. Another possible confusion is that you can get situations where one variable 'a is resolved by your caller in one context, and another 'b is resolved in your own context, the two having the same constraint specification but ending up with different instances because of the different lexical contexts. Any inspiration on that? > 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. Unfortunately that isn't a good model, because the required vtable cannot be build by any single caller. Partly for this reason, I tend to think of this as the caller passing an instance *environment*. The rules for extending that environment as instantiation proceeds are, umm, tricky. shap _______________________________________________ bitc-dev mailing list [email protected] http://www.coyotos.org/mailman/listinfo/bitc-dev
_______________________________________________ bitc-dev mailing list [email protected] http://www.coyotos.org/mailman/listinfo/bitc-dev
