
wren ng thornton wrote:
One of the nice things about the current arrangement is that the package namespace is orthogonal to the module namespace. These two concepts really are orthogonal, so it's good to keep them that way. When they get conflated into one, you end up with Java's import mechanism which is a complete wreck.
Right.
I agree with Maurico that what we really need is to have the tools to be able to rearrange the tree at will. The Haskell language has no business dealing with the provenance of where modules come from--- and forcing modules to be named after their packages would make it do so. Currently, ghc-pkg (or whatever) handles the provenance of making sure that packages are visible to have their modules be loaded. As it stands, this provenance mechanism automatically roots all packages at the same place, but there's no reason it needs to. We just have to come up with the right DSL for scripting ghc-pkg (or equivalently, the right CLI) to be able to play around with the module namespace in a more intelligent way.
For instance, let's assume we have:
> ghc-pkg describe libfoo-0.0.0
... exposed-modules: Data.Foo Control.Bar Control.Bar.Baz ...
Now, if we say:
ghc-pkg expose libfoo-0.0.0
Then any Haskell programs can now load the modules mentioned above, by the names mentioned above. If instead we said something like:
ghc-pkg expose libfoo-0.0.0 at Zot
Then Haskell programs would be able to load the modules by the names Zot.Data.Foo, Zot.Control.Bar, and Zot.Control.Bar.Baz instead. And if we wanted to rebase subtrees then we could say something like:
ghc-pkg expose libfoo-0.0.0:Control.Bar as Quux
Which would make the modules Quux and Quux.Baz available for loading, and would effectively hide libfoo-0.0.0:Data.Foo from being loadable.
If I want to import a module I have to decide on /one/ module name. Since I cannot know at which point in the hierarchy users might have exposed modules from other packages, I must chose the default 'root' point. So, this will not help library authors who want to e.g. import the 'same' module from either mtl or transformers. IMO it makes much more sense to let client packages decide from where in the module hierarchy they want to import modules from another package, rather than forcing users to decide this globally per installation. Thus, grafting should not be done when exposing packages, but rather when actually using them. Your examples above would become ghc -package libfoo-0.0.0@Zot ... resp. ghc -package libfoo-0.0.0:Control.Bar@Quux This would also better play with the way cabal does things: cabal currently ignores hidden/expoosed status of packages; instead it hides everything and then explicitly 'imports' exact versions using the -package option. With a few tweaks to the cabal file syntax, we could easily declare package 'mount points' (even for subtrees) when declaring the dependent packages and this would be tranformed to the ghc command line syntax above. Cheers Ben