Alternatively, I wonder whether the current system of type classes is the right model at all. Although I prefer the Haskell system, I think it is instructive to compare it with the Standard ML (SML) system of structures and functors. My point is that both Haskell and SML impose one of two possible extremes on the user, and suffer for it. With SML, it is as if all instances are explicitly named. SML does not permit user-defined overloading, and so SML is not capable of understanding something such as a "type class of things we can compare", and has a horrible set of kludges to cope with implementing the equality operator. With Haskell, on the other hand, there is no way of referring to a particular instance when you want to. We see a particular consequence of that here, in that (unlike SML), it is not possible to associate an internal type with a given instance. Another problem is that no-one has any control over what instances get exported, because since instances are anonymous there is no way of referring to them. Hence the current procedure is to expose everything to the importer, which is surely a mistake. So if you agree with me up to here, perhaps you are agreed that it is worth while trying to find a middle way, in which we try to combine both approaches. Well I'm not an expert language designer, and I'm doing this off the top of my head late on Thursday evening, so please don't nitpick about syntax; I'm aware that parsing will probably be difficult in all sorts of ways with exactly what I'm writing, but that shouldn't be too hard to tweak. In particular I have followed SML in using "." to express qualification by something, even though Haskell already used "." for something else, because I can't be bothered right now to dig up a better symbol. On the other hand if my whole approach is a pile of elephant dung I apologise for wasting your time, and wish you a happy Christmas/holidays, but do try to find a better way of combining the best of SML functors and Haskell classes. Anyway here is my proposal. (1) We extend type classes to allow them to introduce types. Thus for example I would replace Marcin's first example by class Collectible e where type c -- or we could just omit the "type" keyword, trading clarity -- for conciseness. -- note also that we need a way of expressing a context for -- "c", EG that it's an instance of Eq. empty :: c insert :: c -> e -> c As usual, you can refer to "empty" and "insert" right away, but you can't refer to "c" without extra syntax. We need a way of referring to the particular instance of Collectible. So I suggest something like: singleton :: (method | Collectible e) => e -> method.c singleton el = insert empty el (2) We extend instance declarations in two ways. Firstly and obviously, we need a way of declaring the type c in the instance second declaration. The second thing is to introduce named instance declarations, like this: instance IntList | Collectible Int where type c = [Int] empty = [] insert = (flip(:)) To actually _refer_ to a specific instance, you would qualify with IntList. So you could refer to IntList.c, IntList.empty, IntList.insert, just like you would with SML. But as with Haskell, "empty" and "insert" would continue to be available implicitly. A more complicated example arises when you have instances depending on other instances. EG instance SetCollection | Ord el => Collectible el where type c = Set el empty = emptySet insert = addToSet -- new function, thank Simon Marlow Then, in this case, you would refer to SetCollection.c when you wanted to refer to the type c. However note that in this case we are implicitly using an anonymous use of Ord. Supposing you had previously defined (ignoring questions about overlapping instances for now . . .) instance EccentricOrd | Ord Int where ... and you wanted to define Sets in terms of EccentricOrd. Then I suggest that you use instead SetCollection(EccentricOrd).c and likewise SetCollection(EccentricOrd).empty and Sets(EccentricOrd).insert, though I hope that such monstrous constructions will not often be necessary. When they are, maybe it would be a good idea to allow the user to abbreviate, as in instance EccentricSet | Collectible Int = SetCollection(EccentricOrd) just as you can do in SML. (3) Finally it would be nice to extend the module syntax to allow named instances to be selectively exported and imported, just like variables. If I could ignore all pre-existing Haskell code I would specify that whenever a module has a specific import list, no instances are imported unless specified. However this is politically impossible, so instead I suggest that all anonymous instances continue to be implicitly imported, as now, but that named instances are only imported when named in the import list. EG "import File(instance SetCollection)". Also, I think it would be nice to have something similar to the "qualified" operator, by which class membership is NOT automatically inherited, and would have to be explicitly specified by referring to "SetCollection.insert" or indeed "SetCollection.singleton"; in particular this would provide a clean way of handling overlapping classes. OK, so I realise this is probably not the final answer, but wouldn't it be nice if something along these lines could be got to work?