
On 12/07/2010 22:12, John Meacham wrote:
On Mon, Jul 12, 2010 at 01:50:01PM +0100, Simon Marlow wrote:
Right. I like the idea of packages being able to declare re-exported modules, indeed I considered doing this in GHC (when we needed base3) but decided not to mainly because we would still need PackageImports, and once you have PackageImports you can implement re-exports using that, albeit with more boilerplate. The advantage of direct re-exports, as you say, is that it avoids a conflict when the module is imported. However, since some of the modules would conflict anyway, there didn't seem to be much advantage in avoiding the conflict in some cases but not others.
Well, a main useful case is that I can do -phaskell98 and -phaskell2010 at the same time. So I can make the default jhc behavior be the union of the two languages easily.
That works in GHC too: the modules of those two packages don't overlap. That is partly because we never moved Prelude from base to haskell98. But suppose the Haskell 2010 Prelude had some differences from the Haskell 98 Prelude - then a direct re-export wouldn't work, and you'd be stuck with conflicts again. So my main point is that while direct re-exports avoid conflicts sometimes, they're not a general solution, and eventually you run into the same problems again. There are differences between several Haskell 2010 modules and the equivalent base modules, so you won't be able to use re-exports for those.
There is also some philosophy behind it. I don't like coupling things that don't need to be coupled, such as the interface a library exports and the place that interface is implemented.
I agree with the philosophy, but I don't understand how package re-exports are part of its implementation - the Haskell module system already lets you re-export entities and therefore decouple the implementation from the API.
I think the ability for a package to define an 'interface' built up from other re-exported modules will be very useful going forward, I am not sure how hard something like that would be to implement in ghc, but it may be worth it in the future.
Isn't that what PackageImports lets you do?
Hmm.. maybe. Jhc doesn't have PackageImports, the idea being that you re-export modules rather than importing them from a specific package and exporting their interface. So, it sort of shifts the effort from the interface makers to the implementors, as in, the Haskell 98 Prelude will actually have to be in a module called Compat.Haskell98.Prelude and just re-exported by the 'haskell98' and 'haskell2010' modules.
I don't think the difference is as fundamental as you make out. In Haskell you can already write module A ( module B ) where import B which is the essence of re-exporting a module, and preserves the interface/implementation separation. Now suppose A and B are the same module name, from different packages. To implement this re-export you can either (1) Use a package re-export (in JHC) (2) Somehow avoid A and B being the same, e.g. by having an intermediate like Compat.Haskell98.Prelude (3) Use PackageImports (in GHC) the advantage of (1) is that you can have both packages in scope without a conflict, whereas in (2/3) the two modules can export different interfaces, while still separating the implementation from the interface. I think of PackageImports as just an optimisation that lets you avoid the intermediate module in (2). So again, my point is that in the general case the APIs diverge, so you don't get to do (1), or you only get to do it for some modules, which could be confusing for users.
In one sense 'Compat.Haskell98' sort of acts as a package import, but it isn't actually tied to a package, it just refers to the Compat.Haskell98.Prelude in scope. I also have a large aversion to allowing package names to infect source files carte blanche. It blurs the line between the language itself and the environment the language runs in. It may be neccesarry at some point, but I'll put it off until a case comes up that makes it abundantly clear that it is needed.
I agree with your aversion to putting package names in the source code, which is why we don't advertise PackageImports as an extension that we expect end users to use, and we don't let you use version numbers. Cheers, Simon