
I just took a deeper look at how .NET handles packages, since they have thought through many of the same issues and have a scheme that scales well. There's a great deal of similarity with the schemes we're thinking about for Haskell. The executive summary: - A .NET assembly fulfills the same function as a Haskell package: an assembly is the unit of versioning and distribution, and carries with it a bunch of metadata (author, copyright, etc.). - An assembly is uniquely identified by a triple (name,version,culture). - An assembly travels in a single file (.DLL) - An assembly may define multiple namespaces (like A.B.C), and entities within namespaces. Much like modules in Haskell. - Assemblies are not named directly in source code. C# code (for example) refers to namespaces and entities only. - When compiling C# code, you name the DLLs that contain assemblies to bring into scope (in fact, the transitive closure) using command-line options. - The C# compiler brings a set of assemblies into scope by default (== exposed packages in GHC). - The binary has baked into it the exact identity of the assemblies it was compiled against. - At runtime, the binary might be rebound to different versions of the assemblies it depends on, via a complicated structure of configuration files. So there's no grafting, or even assembly-qualified imports. How do they get away with this? Well, one reason is that namespaces are generally globally unique, because the convention is to use names beginning with an organisation (eg. Microsoft.System). So when you bring a bunch of assemblies into scope, their namespaces generally don't conflict. Interestingly, the assembly story is almost identical to what GHC supports right now, and when we change module identities to include the package name (which I'm working on now), it will be even closer. Not that I necessarily think we can get away with doing nothing to the language, but at lesat this seems to argue for being conservative. Cheers, Simon