
Hi lists, I recently read Simon Peyton Jones' proposal: http://hackage.haskell.org/trac/ghc/wiki/GhcPackages and disagreed with some of the design decisions. (To be fair, the aspects I disagree with are shared with most or all of the other proposals) So I've put an alternative proposal here: http://hackage.haskell.org/trac/ghc/wiki/PackageMounting Discussion is welcome (but only on the libraries@ list, please). Hopefully we can weigh the benefits of each proposal, and reach an agreement and write up a more formal specification within the next few months or so provided that people decide that this is an extension we want to implement. Cheers, Frederik P.S. (I'm sorry that I missed Sven's earlier package mounting thread in July. But I hope the above article covers what my response would have been) -- http://ofb.net/~frederik/

Frederik Eaton
I too have been unconvinced that we need to change the syntax of module imports, to incorporate package identifiers and versions. You make a good case for an alternative mechanism, that keeps all the package information out of the source code, and therefore increases the chances of re-use without modifying the code. The use of the .cabal file to record package-mounting information seems to tie it all together well, in a way that previous mounting proposals have not achieved. Regards, Malcolm

Frederik Eaton wrote:
So I've put an alternative proposal here:
http://hackage.haskell.org/trac/ghc/wiki/PackageMounting
Discussion is welcome (but only on the libraries@ list, please). Hopefully we can weigh the benefits of each proposal, and reach an agreement and write up a more formal specification within the next few months or so provided that people decide that this is an extension we want to implement.
There is not much of content I can say that isn't already covered on the wiki page or in the email you sent when you first proposed this, so let me just say that I am completely convinced that this proposal is The Right Thing. Cheers, Ben

On 10/25/06, Frederik Eaton
It looks nice, but don't you think the -package-base flag ought to take both the package name *and* the mountpoint? Otherwise, this looks like what I've wanted all along, if only I knew it ;-).

On Sun, Oct 29, 2006 at 10:03:32PM -0400, Samuel Bronson wrote:
On 10/25/06, Frederik Eaton
wrote: It looks nice, but don't you think the -package-base flag ought to take both the package name *and* the mountpoint?
My intention was that -package-base specifies a base for the package specified in the preceding -package flag, but I'll clarify it in the document. In other words, it is an optional argument and the syntax is ghc ... -package PACKAGE -package-base BASE ... (giving package PACKAGE mount point BASE)
Otherwise, this looks like what I've wanted all along, if only I knew it ;-).
Excellent, thanks. Frederik -- http://ofb.net/~frederik/

On 10/30/06, Frederik Eaton
On Sun, Oct 29, 2006 at 10:03:32PM -0400, Samuel Bronson wrote:
On 10/25/06, Frederik Eaton
wrote: It looks nice, but don't you think the -package-base flag ought to take both the package name *and* the mountpoint?
My intention was that -package-base specifies a base for the package specified in the preceding -package flag, but I'll clarify it in the document. In other words, it is an optional argument and the syntax is
ghc ... -package PACKAGE -package-base BASE ...
(giving package PACKAGE mount point BASE)
Otherwise, this looks like what I've wanted all along, if only I knew it ;-).
Excellent, thanks.
What about packages with multiple module trees like, say, Cabal? -- Cheers, Lemmih

What about packages with multiple module trees like, say, Cabal?
That's a good question, and I think the right answer is not to do anything special to support them. I assume that what you're referring to with Cabal is that there is no common prefix for all of the module names, but rather a small set of common prefixes (Distribution.*, Language.Haskell.Extension). Under my proposal, if we want to get rid of the 'Distribution' module prefix within the Cabal source code, then we'll have to either rename the Language.Haskell.Extension module, or move it to another package. Best, Frederik -- http://ofb.net/~frederik/

On 10/30/06, Frederik Eaton
What about packages with multiple module trees like, say, Cabal?
That's a good question, and I think the right answer is not to do anything special to support them. I assume that what you're referring to with Cabal is that there is no common prefix for all of the module names, but rather a small set of common prefixes (Distribution.*, Language.Haskell.Extension). Under my proposal, if we want to get rid of the 'Distribution' module prefix within the Cabal source code, then we'll have to either rename the Language.Haskell.Extension module, or move it to another package.
Erg. That sounds icky :-(. Maybe we ought to have a flag that takes package name, default mountpoint, and replacement mountpoint? And the cabal would look like this: The package would export: X11.Types X11.Xlib X11.Xlib.Atom X11.Xlib.Event X11.Xlib.Display ... and have: Default-Bases: X11=Graphics.X11 Other packages would import it like this if they wanted the Types module at Graphics.Unix.X11.Types: Build-Depends: X11(X11=Graphics.Unix.X11) Who knows what the GHC flags ought to look like...

I wouldn't be opposed to this suggestion, if people think that it's not too confusing. It would certainly make many things easier. My original proposal was more conservative in part because I'd thought that people might be reluctant to open up new sinks for design complexity in Haskell programs - but of course, we would hope the effect of Samuel's additional features will be to simplify design in the long run. Frederik On Mon, Oct 30, 2006 at 06:37:16AM -0500, Samuel Bronson wrote:
On 10/30/06, Frederik Eaton
wrote: What about packages with multiple module trees like, say, Cabal?
That's a good question, and I think the right answer is not to do anything special to support them. I assume that what you're referring to with Cabal is that there is no common prefix for all of the module names, but rather a small set of common prefixes (Distribution.*, Language.Haskell.Extension). Under my proposal, if we want to get rid of the 'Distribution' module prefix within the Cabal source code, then we'll have to either rename the Language.Haskell.Extension module, or move it to another package.
Erg. That sounds icky :-(. Maybe we ought to have a flag that takes package name, default mountpoint, and replacement mountpoint? And the cabal would look like this:
The package would export: X11.Types X11.Xlib X11.Xlib.Atom X11.Xlib.Event X11.Xlib.Display ...
and have: Default-Bases: X11=Graphics.X11
Other packages would import it like this if they wanted the Types module at Graphics.Unix.X11.Types: Build-Depends: X11(X11=Graphics.Unix.X11)
Who knows what the GHC flags ought to look like...

Frederik Eaton
It looks nice, but don't you think the -package-base flag ought to take both the package name *and* the mountpoint?
My intention was that -package-base specifies a base for the package specified in the preceding -package flag [...] In other words, it is an optional argument and the syntax is
ghc ... -package PACKAGE -package-base BASE ...
How about something like ghc ... -package PACKAGE@BASE (where the @BASE part is optional)? -k -- If I haven't seen further, it is by standing in the footprints of giants

On Mon, Oct 30, 2006 at 09:39:50AM +0100, Ketil Malde wrote:
Frederik Eaton
writes: It looks nice, but don't you think the -package-base flag ought to take both the package name *and* the mountpoint?
My intention was that -package-base specifies a base for the package specified in the preceding -package flag [...] In other words, it is an optional argument and the syntax is
ghc ... -package PACKAGE -package-base BASE ...
How about something like
ghc ... -package PACKAGE@BASE
(where the @BASE part is optional)?
I don't know. Do we want to prevent packages from ever having '@' in their name? Your suggestion seems reasonable, I just thought that my version would be easier. Also, there's no reason why we couldn't start with my '-package-base' option syntax and then add your '-package PACKAGE@BASE' syntax later if it still seems like a good idea... so maybe we should just postpone the decision. Cheers, Frederik -- http://ofb.net/~frederik/

| > http://hackage.haskell.org/trac/ghc/wiki/PackageMounting | | It looks nice, but don't you think the -package-base flag ought to | take both the package name *and* the mountpoint? | | Otherwise, this looks like what I've wanted all along, if only I knew it ;-). I think most of you know that GHC 6.6 made (IHMO) a significant step forward, by allowing a program to contain multiple modules with the same name, if they are from different packages. That means that package authors can choose module names freely, rather than worry about accidentally colliding with other packages. (We'd regard it as unacceptable if the local variables of a function could not have the same name as the local variables of another procedure!) That still leaves an open question, not resolved by GHC 6.6: what to do if you want to import module M from two different packages into the same module? (A related question is when you have to decide what your module is called.) This can be tackled in at least three different ways, one being Frederik's proposal. Simon and I are not wedded to any particular one, and we'd welcome a consensus on what to do. The state of play is summarised here http://hackage.haskell.org/trac/ghc/wiki/GhcPackages which includes a link to the package-mounting proposal. If you care about this stuff, do debate it -- and please record points that survive a bit of discussion on the Wiki pages. None of this is very hard to implement; the difficulty is settling on a good design. Simon

Simon Peyton-Jones wrote:
| > http://hackage.haskell.org/trac/ghc/wiki/PackageMounting | | It looks nice, but don't you think the -package-base flag ought to | take both the package name *and* the mountpoint? | | Otherwise, this looks like what I've wanted all along, if only I knew it ;-).
I think most of you know that GHC 6.6 made (IHMO) a significant step forward, by allowing a program to contain multiple modules with the same name, if they are from different packages. That means that package authors can choose module names freely, rather than worry about accidentally colliding with other packages.
I think this is true only in a very technical sense. I fear that in practice, library authors will go to great lengths to avoid such overlapping module names, because introducing them will cause too much difficulties for library users. The only way to make halfway sure that this doesn't happen is to use (fixed) module hierarchy prefixes containing (more or less) the package name, as in "Text.ParserCombinators.Parsec", even though technically they aren't forced to do so.
(We'd regard it as unacceptable if the local variables of a function could not have the same name as the local variables of another procedure!)
Yes, but this analogy seems to cover only the problem with internal (package-local, non-exposed) modules. To widen your analogy, we'd regard it as similarly unacceptable if we had to qualify each exported entity with the module name each time we use them, even if we are inside the module that defines them, wouldn't we? Which is today's situation on the package/module level: We have to completely qualify module names with their mount point in the module hierarchy, even when refering to them from inside the package that defines them. I see, however, one point with Frederik's proposal that isn't clear to me: Assume library A uses library B. Then, presumably, lib A must chose a mount point for its use of lib B. Now imagine a program P wants to use lib A as well as directly import some module from lib B. Is P now free to give lib B its own mount point, independent of the one that was chosen by lib A? I think this should definitely be possible. There may, however, be some issues regarding implementation: Can a compilation system share code between both 'versions' of lib B (I assume they are /not/ really different versions but exactly the same one, only referred to via a different 'mount point')? Hmm, maybe this isn't really a problem. The compiler could simply alias the module names, similar as to what it does for 'import M as N'.
That still leaves an open question, not resolved by GHC 6.6: what to do if you want to import module M from two different packages into the same module?
What if I want to import them into /different/ modules (which are nevertheless part of the same package)? Can this be easily accomplished with ghc-6.6? Cheers Ben

[narrowing to libraries] | > I think most of you know that GHC 6.6 made (IHMO) a significant step | > forward, by allowing a program to contain multiple modules with the same | > name, if they are from different packages. That means that package | > authors can choose module names freely, rather than worry about | > accidentally colliding with other packages. | | I think this is true only in a very technical sense. I fear that in | practice, library authors will go to great lengths to avoid such | overlapping module names, because introducing them will cause too much | difficulties for library users. The only way to make halfway sure that this | doesn't happen is to use (fixed) module hierarchy prefixes containing (more | or less) the package name, as in "Text.ParserCombinators.Parsec", even | though technically they aren't forced to do so. Why would authors go to great lengths to avoid overlapping module names? The only possible penalty of overlap is that it's a bit awkward to import modules with the same name into the same module. But that's always fixable by making a two-line impedance-matching module. I feel I'm missing your point. | I see, however, one point with Frederik's proposal that isn't clear to me: | | Assume library A uses library B. Then, presumably, lib A must chose a mount | point for its use of lib B. Now imagine a program P wants to use lib A as | well as directly import some module from lib B. Is P now free to give lib B | its own mount point, independent of the one that was chosen by lib A? Oh yes, of course! The mount point simply affects the name space seen by the import declarations in a particular compilation. There is no implementation difficulty here. | > That still leaves an open question, not resolved by GHC 6.6: what to do | > if you want to import module M from two different packages into the same | > module? | | What if I want to import them into /different/ modules (which are | nevertheless part of the same package)? Can this be easily accomplished | with ghc-6.6? Yes, certainly. Suppose that package 'foo' and 'bar' both contain module M. Then you want to import foo.M into module X, and bar.M into module Y. Easy: just compile X with '-package foo' and Y with '-package bar'. The difficulty arises only if you want to import foo.M and bar.M into the *same* module. Indeed, the difference between Plan B and C (in the terminology of the GhcPackages page) is only whether you say ghc X.hs -package foo -package bar where module X import M from "foo" import M from "bar" or whether you say ghc -package foo@Foo -package bar@Bar X.hs where module X import Foo.M import Bar.M The two are really very close --- but the nuances are different and they are important. Simon

Simon Peyton-Jones wrote:
[narrowing to libraries]
Um, yes, sorry.
| > I think most of you know that GHC 6.6 made (IHMO) a significant step | > forward, by allowing a program to contain multiple modules with the same | > name, if they are from different packages. That means that package | > authors can choose module names freely, rather than worry about | > accidentally colliding with other packages. | | I think this is true only in a very technical sense. I fear that in | practice, library authors will go to great lengths to avoid such | overlapping module names, because introducing them will cause too much | difficulties for library users. The only way to make halfway sure that this | doesn't happen is to use (fixed) module hierarchy prefixes containing (more | or less) the package name, as in "Text.ParserCombinators.Parsec", even | though technically they aren't forced to do so.
Why would authors go to great lengths to avoid overlapping module names? The only possible penalty of overlap is that it's a bit awkward to import modules with the same name into the same module. But that's always fixable by making a two-line impedance-matching module.
I feel I'm missing your point.
The point is about causing maintenance headaches in the long run, see below.
| > That still leaves an open question, not resolved by GHC 6.6: what to do | > if you want to import module M from two different packages into the same | > module? | | What if I want to import them into /different/ modules (which are | nevertheless part of the same package)? Can this be easily accomplished | with ghc-6.6?
Yes, certainly. Suppose that package 'foo' and 'bar' both contain module M. Then you want to import foo.M into module X, and bar.M into module Y. Easy: just compile X with '-package foo' and Y with '-package bar'.
Ok, that seems easy enough. Especially if you only have one or just a few such conflicts. However, suppose people take your advice (see above) and start writing lots of libraries with module names that are no longer carefully chosen to have a high probability of being globally unique, in turn causing more and more such name clashes for users of these libraries. I think it is quite clear that individually resolving such clashes for each module where such a clash happens will scale poorly to larger projects. In contrast, resolving the name clash once and for all (that is, per package) by chosing an appropriate 'mount point' for each imported package (if the default one isn't apropriate) will scale nicely and require a minimum of maintenance. [Besides, there is currently no way to specify module specific options when using cabal, right? The manual says "Options required only by one module may be specified by placing an OPTIONS_GHC pragma in the source file affected". Which means currently one has to use, more or less, plan C or else avoid using cabal. You have probably guessed that plan C is the one I favour least ;-] Cheers, Ben
participants (7)
-
Benjamin Franksen
-
Frederik Eaton
-
Ketil Malde
-
Lemmih
-
Malcolm Wallace
-
Samuel Bronson
-
Simon Peyton-Jones