RE: module namespaces with "Prelude"

It happens in Hugs, too, but somewhat differently. Here's a test case. Go to /foo and do mkdir Bar. In Bar, create IO.hs and make its contents: module Bar.IO where then also in Bar create Foo.hs module Bar.Foo where import IO Then when in directory Bar load ghci (using 5.02.1) and load Bar.Foo and you'll get: IO.hs: file name does not match module name `IO' Quit ghci, load hugs and load Bar.Foo and you'll get: ERROR "Foo.hs" - Module "IO" not previously loaded (worse things can happen in hugs -- if say Bar.IO imported Bar.Foo and plain Bar.Foo imported plain old IO hugs will complain about cyclic modules) if you are in /foo instead of /foo/Bar when you load ghci and set paths correctly it will work. I don't know that this is exactly a bug in the software as much as it's just somewhat underspecified what to do in these situations (I could be wrong though). IMO if you say in an import "import XXX" and it looks in XXX.(l)hs and the module names is "YYY.XXX" it should keep looking instead of just dying. I don't really know what repurcussions this will have, though. -- Hal Daume III "Computer science is no more about computers | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume On Mon, 22 Apr 2002, Simon Peyton-Jones wrote:
Hal,
If your question is GHC-specific, send it to ghc-users not the haskell list.
And it would save time if you could be more specific. Say what compiler you are using, enclose a test case, etc. Otherwise we're all guessing.
Simon
| -----Original Message----- | From: Hal Daume III [mailto:hdaume@ISI.EDU] | Sent: 23 April 2002 03:21 | To: Alastair Reid | Cc: Haskell Mailing List | Subject: Re: module namespaces with "Prelude" | | | Ah, so the problem was that even though I had the superdir of | NLP in my path, I was actually loading the modules in ghci | from the NLP directory. Still, I find this behavior odd, | since even if I were in the NLP directory I could not import | "NLP.Foo" simply as "Foo", I don't see why I should be | allowed to (try to) import "NLP.Prelude" simply as "Prelude", | thus messing stuff up... | | -- | Hal Daume III | | "Computer science is no more about computers | hdaume@isi.edu | than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume | | On 23 Apr 2002, Alastair Reid wrote: | | > | > >>>>> "#Hal" == Hal Daume
writes: | > | > > I'm developing my package "NLP" for supporting common NLP | functions | > > and have a set of functions/datatypes that are common to | almost all | > > of my modules and I wanted to separate them off into an | > > "NLP.Prelude" file, but this seems not to work. One of | my modules | > > imports Prelude (the Haskell one) directly so I can hide a few | > > definitions, but then it looks at NLP/Prelude.lhs and | complains that | > > the name of that module "NLP.Prelude" doesn't match "Prelude". | > > SHould I simply name my module "NLP.NLPPrelude" or | something (which | > > is ugly, imo) or what? | > | > The only change that hierarchial module namespaces make is that the | > dots become a legal part of the name and that compilers have a | > sensible way of mapping them onto filenames such as | replacing dots by | > slashes. So, under the new scheme, these names are different and | > unrelated | > | > Prelude NLP.Prelude User.Hal.Daume.NLP.Prelude | > | > in the same way that these names were different and | unrelated in the | > old scheme. | > | > Prelude NLP_Prelude User_Hal_Daume_NLP_Prelude | > | > If you are seeing something other than that, the problem is | with your | > compiler or the way you are using command line arguments to your | > compiler (e.g., Hugs' import chasing mechanism has some interesting | > interactions with hierarchial namespaces) and you should | say which one | > you're using and how you're using it. | > | > -- | > Alastair Reid | > | | _______________________________________________ | Haskell mailing list | Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell |

[copied to original recipients along with the original bug report] On ghc-bugs, Hal Daume reported problems with Hugs (and ghci) where importing IO.hs causes a module called Bar.IO (i.e., Bar/IO.hs) to be loaded - leading to the load to fail. I've systematically tried every way of invoking Hugs (December 2001) that makes sense (and a few that don't) and didn't find any that worked. Here's what I tried: cd /tmp mkdir Bar cat > Bar/Foo.hs module Bar.Foo where import IO cat > Bar/IO.hs module Bar.IO where hugs Bar.Foo # unexpected failure: confuses Bar.IO for IO hugs -P.: Bar.Foo # unexpected failure: confuses Bar.IO for IO hugs Bar.Foo.hs # expected failure: Bar.Foo.hs doesn't exist hugs Bar/Foo.hs # unexpected failure: confuses Bar.IO for IO cd Bar hugs Bar.Foo # expected failure: Can't find Bar.Foo hugs Foo # unexpected failure: confuses Bar.IO for IO hugs -P..: Bar.Foo # unexpected failure: confuses Bar.IO for IO Did I do the wrong thing or do we need to tweak the loader? (I didn't test with import chasing turned off - could that be it?) -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/ It happens in Hugs, too, but somewhat differently. Here's a test case. Go to /foo and do mkdir Bar. In Bar, create IO.hs and make its contents: module Bar.IO where then also in Bar create Foo.hs module Bar.Foo where import IO Then when in directory Bar load ghci (using 5.02.1) and load Bar.Foo and you'll get: IO.hs: file name does not match module name `IO' Quit ghci, load hugs and load Bar.Foo and you'll get: ERROR "Foo.hs" - Module "IO" not previously loaded (worse things can happen in hugs -- if say Bar.IO imported Bar.Foo and plain Bar.Foo imported plain old IO hugs will complain about cyclic modules) if you are in /foo instead of /foo/Bar when you load ghci and set paths correctly it will work. I don't know that this is exactly a bug in the software as much as it's just somewhat underspecified what to do in these situations (I could be wrong though). IMO if you say in an import "import XXX" and it looks in XXX.(l)hs and the module names is "YYY.XXX" it should keep looking instead of just dying. I don't really know what repurcussions this will have, though. -- Hal Daume III "Computer science is no more about computers | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume On Mon, 22 Apr 2002, Simon Peyton-Jones wrote:
Hal,
If your question is GHC-specific, send it to ghc-users not the haskell list.
And it would save time if you could be more specific. Say what compiler you are using, enclose a test case, etc. Otherwise we're all guessing.
Simon
| -----Original Message----- | From: Hal Daume III [mailto:hdaume@ISI.EDU] | Sent: 23 April 2002 03:21 | To: Alastair Reid | Cc: Haskell Mailing List | Subject: Re: module namespaces with "Prelude" | | | Ah, so the problem was that even though I had the superdir of | NLP in my path, I was actually loading the modules in ghci | from the NLP directory. Still, I find this behavior odd, | since even if I were in the NLP directory I could not import | "NLP.Foo" simply as "Foo", I don't see why I should be | allowed to (try to) import "NLP.Prelude" simply as "Prelude", | thus messing stuff up... | | -- | Hal Daume III | | "Computer science is no more about computers | hdaume@isi.edu | than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume | | On 23 Apr 2002, Alastair Reid wrote: | | > | > >>>>> "#Hal" == Hal Daume
writes: | > | > > I'm developing my package "NLP" for supporting common NLP | functions | > > and have a set of functions/datatypes that are common to | almost all | > > of my modules and I wanted to separate them off into an | > > "NLP.Prelude" file, but this seems not to work. One of | my modules | > > imports Prelude (the Haskell one) directly so I can hide a few | > > definitions, but then it looks at NLP/Prelude.lhs and | complains that | > > the name of that module "NLP.Prelude" doesn't match "Prelude". | > > SHould I simply name my module "NLP.NLPPrelude" or | something (which | > > is ugly, imo) or what? | > | > The only change that hierarchial module namespaces make is that the | > dots become a legal part of the name and that compilers have a | > sensible way of mapping them onto filenames such as | replacing dots by | > slashes. So, under the new scheme, these names are different and | > unrelated | > | > Prelude NLP.Prelude User.Hal.Daume.NLP.Prelude | > | > in the same way that these names were different and | unrelated in the | > old scheme. | > | > Prelude NLP_Prelude User_Hal_Daume_NLP_Prelude | > | > If you are seeing something other than that, the problem is | with your | > compiler or the way you are using command line arguments to your | > compiler (e.g., Hugs' import chasing mechanism has some interesting | > interactions with hierarchial namespaces) and you should | say which one | > you're using and how you're using it. | > | > -- | > Alastair Reid | > | | _______________________________________________ | Haskell mailing list | Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell |

On Tuesday, April 23, 2002, at 06:09 , Alastair Reid wrote:
[copied to original recipients along with the original bug report]
On ghc-bugs, Hal Daume reported problems with Hugs (and ghci) where importing IO.hs causes a module called Bar.IO (i.e., Bar/IO.hs) to be loaded - leading to the load to fail.
I've systematically tried every way of invoking Hugs (December 2001) that makes sense (and a few that don't) and didn't find any that worked. Here's what I tried:
cd /tmp mkdir Bar
cat > Bar/Foo.hs module Bar.Foo where import IO
cat > Bar/IO.hs module Bar.IO where
hugs Bar.Foo # unexpected failure: confuses Bar.IO for IO
hugs -P.: Bar.Foo # unexpected failure: confuses Bar.IO for IO
hugs Bar.Foo.hs # expected failure: Bar.Foo.hs doesn't exist
hugs Bar/Foo.hs # unexpected failure: confuses Bar.IO for IO
cd Bar hugs Bar.Foo # expected failure: Can't find Bar.Foo
hugs Foo # unexpected failure: confuses Bar.IO for IO
hugs -P..: Bar.Foo # unexpected failure: confuses Bar.IO for IO
Did I do the wrong thing or do we need to tweak the loader?
(I didn't test with import chasing turned off - could that be it?)
-- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/
We're approaching a dark corner here, where the principle of a single, hierarchical module namespace clashes with the established idea of searching for modules along an externally defined directory path. In Hugs, and I think in ghci as well, the implementation of hierarchical modules allows a module hierarchy with several roots. Not only is it possible to define multiple roots in the search path, the current directory is also an implicit root, and if a module is being imported by another module, the directory where the importing module was found is another one. Now, since there's nothing that prevents the directory hierarchies starting at these roots from overlapping, we have a potential for ambiguity when we want to map module names to filenames. In the examples above, the module defined in Bar/IO.hs is given the name Bar.IO. However, according to the way we map module names onto files, Bar/IO.hs will also appear to be a valid implementation of module IO, since the directory Bar is implicitly an alternative root to the module hierarchy. One solution would then be to start parsing Bar/IO.hs until we can determine if its module name matches the name suggested by its file name and the current root. However, implementing such a check seems like a big hack, when the real problem is the questionable support for multiple roots. It's also not a trivial thing to do, since we would need to backtrack from parsing and continue the module search in case of a name mismatch. One might also argue that the problem is these extra roots that are implicitly added to the search path. Arguably, dropping the current directory and the directory of the importing module from the search path would solve the problems listed above. But there's still a possibility to list overlapping directories in the search path proper, so dropping the implicit directories wouldn't really cure the disease, only make it less prominent. Furthermore, this feature is there because it has been in Hugs for a long time, and many people seem to rely on it quite heavily. Still, the current status is unsatisfactory. Of the two ways forward pointed at above, dropping the implicit roots and putting the burden on the programmer to define consistent search paths is by far the easiest one to implement. However, one should bear in mind that this will disturb many people, particularly those who don't use hierarchical modules. Doing speculative parsing of module headers looks more robust, but it would indeed be a complicated way of resolving ambiguities that shouldn't be there in the first place. A fully satisfactory solution can't be obtained, I think, unless we make the whole module hierarchy single-rooted. That would make it harder to integrate local modules with the standard libraries, though, and would probably need some kind of module "mounting" facility to be practical. However, I don't believe we're ready for such an experiment just yet. All in all, dropping all implicit directories from the search path gets my vote. -- Johan

Now, since there's nothing that prevents the directory hierarchies starting at these roots from overlapping, we have a potential for ambiguity when we want to map module names to filenames.
This suggests that we might want to modify the search algorithm to find all matches and report and error if two or more candidate files are found. If this is a big performance hit, we could make it a :set option.
Still, the current status is unsatisfactory. Of the two ways forward pointed at above, dropping the implicit roots and putting the burden on the programmer to define consistent search paths is by far the easiest one to implement. However, one should bear in mind that this will disturb many people, particularly those who don't use hierarchical modules.
Perhaps this disruption could be reduced by making the use of implicit roots a flag you can turn on or off and being careful to avoid overlapping names in the libraries we distribute with Hugs. Naive users would then get to use all the libraries but, since naive users don't use hierarchial namespaces (by my definition :-) they should not run into these problems. Sophisticated users would turn off the use of implicit roots and turn on ambiguous filename checks and would perhaps convert their code to use hierarchial namespaces. -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/

On Thursday, April 25, 2002, at 03:00 , Alastair Reid wrote:
Now, since there's nothing that prevents the directory hierarchies starting at these roots from overlapping, we have a potential for ambiguity when we want to map module names to filenames.
This suggests that we might want to modify the search algorithm to find all matches and report and error if two or more candidate files are found. If this is a big performance hit, we could make it a :set option.
But wouldn't that just prohibit the use of module names that also appear in the standard libraries? At least we need to stop searching the directory of the importing module to make something useful of this idea. -- Johan

This suggests that we might want to modify the search algorithm to find all matches and report and error if two or more candidate files are found. If this is a big performance hit, we could make it a :set option.
But wouldn't that just prohibit the use of module names that also appear in the standard libraries? At least we need to stop searching the directory of the importing module to make something useful of this idea.
It would tell you when you're on thin ice. -- Alastair

tor 2002-04-25 klockan 01.07 skrev Johan Nordlander:
One might also argue that the problem is these extra roots that are implicitly added to the search path. Arguably, dropping the current directory and the directory of the importing module from the search path would solve the problems listed above. But there's still a possibility to list overlapping directories in the search path proper, so dropping the implicit directories wouldn't really cure the disease, only make it less prominent. Furthermore, this feature is there because it has been in Hugs for a long time, and many people seem to rely on it quite heavily.
But how would adding the directory of an importing module make any difference? Assuming non-hierarchical names, if the importing module is found, then it's directory already must be in the seach path. So there is no reason to add it.
All in all, dropping all implicit directories from the search path gets my vote.
Dropping all implicit directories but the current directory gets mine. On the other hand, adding "." to the search path is no big trouble, and then it will work exactly like java. A compiler could even allow search paths to be tar-files (or tar.gz, tar.bz2, zip, jar, ...). Regards, Martin

On Thursday, April 25, 2002, at 09:20 , Martin Norbäck wrote:
tor 2002-04-25 klockan 01.07 skrev Johan Nordlander:
One might also argue that the problem is these extra roots that are implicitly added to the search path. Arguably, dropping the current directory and the directory of the importing module from the search path would solve the problems listed above. But there's still a possibility to list overlapping directories in the search path proper, so dropping the implicit directories wouldn't really cure the disease, only make it less prominent. Furthermore, this feature is there because it has been in Hugs for a long time, and many people seem to rely on it quite heavily.
But how would adding the directory of an importing module make any difference?
Assuming non-hierarchical names, if the importing module is found, then it's directory already must be in the seach path. So there is no reason to add it.
This is useful in combination with another traditional Hugs feature: to load or import a module using its concrete filename. That is, if I write :l "/some/exotic/directory/module.hs" the directory "/some/exotic/directory/" is implicitly added to the search path during processing of any import clauses within module.hs. I admit that it is a dubious feature, but it (too) seems to be widely in use.
All in all, dropping all implicit directories from the search path gets my vote.
Dropping all implicit directories but the current directory gets mine.
A reasonable compromise, although it wouldn't address the last two examples of module confusion that Alastair reported. -- Johan

Johan:
A reasonable compromise, although it wouldn't address the last two examples of module confusion that Alastair reported.
Just to clarify: my problem was that I couldn't find any way of making Hal's example work. If there's been anything which worked, I'd have said it was a bug in the documentation or a bug in the user :-) If we can agree on anything which makes the example work in Hugs (and ideally is compatible with ghci or is also adopted by ghci) then I'll be happy. -- Alastair
participants (4)
-
Alastair Reid
-
Hal Daume III
-
Johan Nordlander
-
Martin Norbäck