Hierarchical module namespace extension not sufficiently flexible
All, So here's the problem: we have a binding to a large foreign library (GTK) which we are trying to fit nicely into hierarchical module name space. It would live under Graphics.UI.Gtk Graphics.UI.Gtk.Button Graphics.UI.Gtk.Frame ... etc Now there are over 100 modules directly under Graphics.UI.Gtk and you don't want to have to import each one of them separately. Of course you will not use all of them in one module but you might reasonably use 20+ of them. So it'd be nice to be able to say:
import Graphics.UI.Gtk or import qualified Graphics.UI.Gtk as Gtk
But now we have a problem. These import directives import a flat namespace, or a flat namespace qualified by a single module alias (ie Gtk in the second example). But the Gtk modules are deliberatly designed to have hierarchical names. You cannot simply combine them all together into a flat namespace without falling back to the trick of prefixing each function name with the module name. So while we would like to be able for users to do this:
import Graphics.UI.Gtk
... Button.setLabel ...
They will instead have to say:
import Graphics.UI.Gtk
... buttonSetLabel ...
Which is one of the things that the hierarchical module namespace extension was trying to get rid of! All the other language bindings for Gtk (apart from C) use the former import and useage style. It doesn't make us look good! :-) So my question is: have I overlooked something or is this really not possible at the moment. And secondly, if it is currently not possible is there a 'nice' extension that would allow this sort of thing. (Where nice probably means Haskell98 compatible / 'doesn't' break existing programs) How about:
module Graphics.UI.Gtk (
module qualified Graphics.UI.Gtk.Button as Button ... ) where
import Graphics.UI.Gtk.Button
or equivalently(?):
module Graphics.UI.Gtk (
module qualified Button ... ) where
import Graphics.UI.Gtk.Button as Button
Duncan Ps there's a oddity I found where if you say:
module Foo ( module Bar )
import qualified Bar
then module Foo exports precisely nothing. But there's no error or warning.
Hello, Duncan Coutts wrote: ...
So while we would like to be able for users to do this:
import Graphics.UI.Gtk
... Button.setLabel ...
I don't think you can do things like this with the current module system. One possible extension that might solve this problem is to allow partial qualified names, i.e. a qualified name only specifies enough of the _ending_ of the full qualified name to make it unambiguous. I think this is more or less compatable (of course it would invalidate some programs but not a lot) as the current behavior is simply the special case where we specify the whole name.
(Off the top of my head) I think this is quite easy to implement. For example in one of the Haskell front-ends we have here at OGI (Programatica), there is a "resolve" pass that replaces qualified names by the origianl names they refer to. During this pass we can detect ambiguous or undefined names. All one would have to do is modify the lookup function to check for suffixes rather then equality. I am not sure how other implementations work, but I'd imagine one would have to do something similar.
Ps there's a oddity I found where if you say:
module Foo ( module Bar )
import qualified Bar
then module Foo exports precisely nothing. But there's no error or warning.
This is the correct behaviour (at least according to the spec). The meaning of "module" exports is not as simple as one might expect. For details check out the report, for even more details you could take a look at "A Formal Specification of the Haskell 98 Module System". I agree that a warning in such situations may be nice. -iavor
On Fri, 2004-12-17 at 14:26 +0000, Duncan Coutts wrote:
All,
So here's the problem: we have a binding to a large foreign library (GTK) which we are trying to fit nicely into hierarchical module name space. It would live under
Graphics.UI.Gtk Graphics.UI.Gtk.Button Graphics.UI.Gtk.Frame ... etc
Now there are over 100 modules directly under Graphics.UI.Gtk and you don't want to have to import each one of them separately. Of course you will not use all of them in one module but you might reasonably use 20+ of them.
So it'd be nice to be able to say:
[snip] Or as an alternative to exporting qualified names as I proposed before (ie Graphics.UI.Gtk exports the qualified name "Button.label") how about this: import qualified Graphics.UI.Gtk.* which just means import every module under Graphics.UI.Gtk qualified with it's module name so that then you could reference: Button.label A downside to such a scheme is that it might make it too easy to import internal modules or modules that are not supposed to be used together. I think on balance I prefer putting the power in the hands of the library author by letting modules export other modules' contents qualified with the module name module Graphics.UI.Gtk ( qualified module Graphics.UI.Gtk.Button as Button, ... Any other ideas of how to wrap large existing name spaces? The .Net and Java people would have the same problem: to use nice qualified names under the current module system, users would have to import 100's of modules. Duncan
Duncan Coutts (duncan.coutts@worc.ox.ac.uk) wrote:
Or as an alternative to exporting qualified names as I proposed before (ie Graphics.UI.Gtk exports the qualified name "Button.label") how about this:
import qualified Graphics.UI.Gtk.*
which just means import every module under Graphics.UI.Gtk qualified with it's module name so that then you could reference:
Button.label
A downside to such a scheme is that it might make it too easy to import internal modules or modules that are not supposed to be used together.
But does this option not contradict the argument against the 1st one, i.e. that one should know the internal structure, i.e. hierarchy of the lib in order to know what he is doing by importing everything? Sincerely, Gour -- Registered Linux User | #278493 GPG Public Key | 8C44EDCD
On Sat, 2005-03-05 at 18:40 +0100, Gour wrote:
Duncan Coutts (duncan.coutts@worc.ox.ac.uk) wrote:
Or as an alternative to exporting qualified names as I proposed before (ie Graphics.UI.Gtk exports the qualified name "Button.label") how about this:
import qualified Graphics.UI.Gtk.*
which just means import every module under Graphics.UI.Gtk qualified with it's module name so that then you could reference:
Button.label
A downside to such a scheme is that it might make it too easy to import internal modules or modules that are not supposed to be used together.
But does this option not contradict the argument against the 1st one, i.e. that one should know the internal structure, i.e. hierarchy of the lib in order to know what he is doing by importing everything?
In the first proposal: import Graphics.UI.Gtk -- which brings Button.label into scope I don't need to know much about the internal layout of the library. I only need to know that it exports the Button module or the Label module etc. There can be Graphics.UI.Gtk.Internal or Graphics.UI.Gtk.Types which should not be directly imported by client code. Users need not know they are there. However if I can import qualified Graphics.UI.Gtk.* or worse import Graphics.UI.Gtk.* then it's possible that I could be bitten by unexpected name clashes or something. In the latter case it's the user who has the power and who has to be aware when they use it. In the former case the library author has the power and presumably we can trust them to be sensible with it. It does mean that as I library author I'm sort of forcing you to use qualified names when perhaps you did not want to. But for some libraies you really can't sensibly use them with a flat name space. There are dozen different things in Gtk+ that have a 'value' property. Duncan
On Saturday 05 March 2005 20:06, Duncan Coutts wrote:
It does mean that as I library author I'm sort of forcing you to use qualified names when perhaps you did not want to. But for some libraies you really can't sensibly use them with a flat name space. There are dozen different things in Gtk+ that have a 'value' property.
I'd be interested to know why you don't use classes for that. Ben
On Sun, 2005-03-06 at 01:29 +0100, Benjamin Franksen wrote:
On Saturday 05 March 2005 20:06, Duncan Coutts wrote:
It does mean that as I library author I'm sort of forcing you to use qualified names when perhaps you did not want to. But for some libraries you really can't sensibly use them with a flat name space. There are dozen different things in Gtk+ that have a 'value' property.
I'd be interested to know why you don't use classes for that.
Because they don't share an interface or some common semantics. They just happen to use the same name. I don't think it's good design to use classes just because you want ad-hoc overloading. (We do use Haskell classes to model Gtk+ classes) Indeed this isn't even overloading really, the Gtk+ system we are wrapping uses a hierarchical module namespace itself (albeit in C following the naming convention namespace_class_method). We are just trying to model this in Haskell with Haskell modules. Every other language binding for Gtk+ does this: C++, Java, Perl, Python, Ruby, OCaml etc. We can do it too except that to use qualified names, users would have to import dozens of modules: import Graphics.UI.Gtk.This import Graphics.UI.Gtk.That import Graphics.UI.Gtk.TheOther. So at the moment we prefix the module name to everything in the module, "buttonLabel" so we can export everything through Graphics.UI.Gtk whereas we (and the designers of the hierarchical module namespace extension) would prefer people to be able to use "Button.label". Duncan
On Sunday 06 March 2005 13:23, Duncan Coutts wrote:
On Sun, 2005-03-06 at 01:29 +0100, Benjamin Franksen wrote:
On Saturday 05 March 2005 20:06, Duncan Coutts wrote:
It does mean that as I library author I'm sort of forcing you to use qualified names when perhaps you did not want to. But for some libraries you really can't sensibly use them with a flat name space. There are dozen different things in Gtk+ that have a 'value' property.
I'd be interested to know why you don't use classes for that.
Because they don't share an interface or some common semantics. They just happen to use the same name.
I don't think it's good design to use classes just because you want ad-hoc overloading.
(We do use Haskell classes to model Gtk+ classes)
Indeed this isn't even overloading really, the Gtk+ system we are wrapping uses a hierarchical module namespace itself (albeit in C following the naming convention namespace_class_method). We are just trying to model this in Haskell with Haskell modules. Every other language binding for Gtk+ does this: C++, Java, Perl, Python, Ruby, OCaml etc.
We can do it too except that to use qualified names, users would have to import dozens of modules: import Graphics.UI.Gtk.This import Graphics.UI.Gtk.That import Graphics.UI.Gtk.TheOther.
So at the moment we prefix the module name to everything in the module, "buttonLabel" so we can export everything through Graphics.UI.Gtk whereas we (and the designers of the hierarchical module namespace extension) would prefer people to be able to use "Button.label".
Ok, thanks for the detailed answer. Cheers, Ben
On 06/03/2005, at 11:23 PM, Duncan Coutts wrote:
We can do it too except that to use qualified names, users would have to import dozens of modules: import Graphics.UI.Gtk.This import Graphics.UI.Gtk.That import Graphics.UI.Gtk.TheOther.
Not that this is a fantastic solution (and perhaps you're doing this already), but one technique is to make a module named Graphics.UI.Gtk (i.e. Graphics/UI/Gtk.hs), which imports all the submodules for you and re-exports all of them: module Graphics.UI.Gtk ( Graphics.UI.Gtk.This , Graphics.UI.Gtk.That , Graphics.UI.Gtk.TheOther ) where import Graphics.UI.Gtk.This import Graphics.UI.Gtk.That import Graphics.UI.Gtk.TheOther (or you can call the module Graphics.UI.Gtk.all, or something.) It's somewhat feasible to do if you're machine-generating it, but obviously pretty unmaintainable if you have to write it all by hand ... -- % Andre Pang : trust.in.love.to.save
On Mon, 2005-03-07 at 17:39 +1100, Andre Pang wrote:
On 06/03/2005, at 11:23 PM, Duncan Coutts wrote:
We can do it too except that to use qualified names, users would have to import dozens of modules: import Graphics.UI.Gtk.This import Graphics.UI.Gtk.That import Graphics.UI.Gtk.TheOther.
Not that this is a fantastic solution (and perhaps you're doing this already), but one technique is to make a module named Graphics.UI.Gtk (i.e. Graphics/UI/Gtk.hs), which imports all the submodules for you and re-exports all of them:
Yes indeed that is what we do. The disadvantage of doing this over importing each module individually (which we do not encourage as it's impractical) is that now one must export a flat namespace but Gtk+ is not a flat namespace! When you import each module individually you can import qualified: import qualified Graphics.UI.Gtk.Button as Button and then use: Button.label But since we use import Graphics.UI.Gtk then you can only use 'label' or 'Gtk.label' but that does not distinguish between the different Gtk+ modules which use 'label'. So sadly we have to prefix the module name to each exported entity so you say for example: button <- buttonNew buttonSetLabel button "bla" Of course what we would like to be able to do the imports/exports such that users can say: button <- Button.new Button.setLabel button "bla" or if using the Yahu-style interface it'd be: button <- Button.new [Button.label := "bla"] Duncan
On Sat, 05 Mar 2005 17:03:38 +0000, Duncan Coutts > module Graphics.UI.Gtk (
qualified module Graphics.UI.Gtk.Button as Button, ...
I like this idea a lot! It wouldn't break existing stuff (would it?), and it really seems like it should already be in there. I mean if you can import and export modules, it doesn't make sense that qualified imports are allowed but not qualified exports. This strategy also allows the library author some control over the library's structure. I might be missing something but this really does look "nice". /S -- Sebastian Sylvan +46(0)736-818655 UIN: 44640862
On Sat, 2005-03-05 at 22:15 +0100, Sebastian Sylvan wrote:
On Sat, 05 Mar 2005 17:03:38 +0000, Duncan Coutts > module Graphics.UI.Gtk (
qualified module Graphics.UI.Gtk.Button as Button, ...
I like this idea a lot!
Great. We "just" have to persuade other people around here of the same, in particular compiler implementors and the authors of the Hierarchical Modules Addenda.
It wouldn't break existing stuff (would it?), and it really seems like it should already be in there. I mean if you can import and export modules, it doesn't make sense that qualified imports are allowed but not qualified exports.
I think the reason it was not added before is down to the fact that modules don't really export other modules. They just export other modules contents. (Also it was a deliberately conservative extension.) Exporting qualified names doesn't really change that, we're just exporting the contents of a module but with qualified names.
This strategy also allows the library author some control over the library's structure. I might be missing something but this really does look "nice".
You mean it would allow a 'virtual' structure to be exported that does not match the actual internal structure of the library? I suppose that's true. I think this is probably a bonus (so long as library authors use it sensibly). For example in Gtk2Hs, in actual fact we do not have Graphics.UI.Gtk.AboutDialog we have Graphics.UI.Gtk.Windows.AboutDialog That is we have an additional "category" layer. Otherwise we would have all 130 modules directly in the Graphics/UI/Gtk/ directory which we would find much harder to manage. So it would be nice to keep this structure but to export a 'virtual' module structure that does not mention the category. ie: module Graphics.UI.Gtk ( qualified module Graphics.UI.Gtk.Windows.AboutDialog as AboutDialog ... ) where import Graphics.UI.Gtk.Windows.AboutDialog ... Duncan
Hello, On Sun, 06 Mar 2005 12:21:01 +0000, Duncan Coutts <duncan.coutts@worc.ox.ac.uk> wrote:
On Sat, 2005-03-05 at 22:15 +0100, Sebastian Sylvan wrote:
On Sat, 05 Mar 2005 17:03:38 +0000, Duncan Coutts > module Graphics.UI.Gtk (
qualified module Graphics.UI.Gtk.Button as Button, ...
I like this idea a lot!
Great. We "just" have to persuade other people around here of the same, in particular compiler implementors and the authors of the Hierarchical Modules Addenda.
It wouldn't break existing stuff (would it?), and it really seems like it should already be in there. I mean if you can import and export modules, it doesn't make sense that qualified imports are allowed but not qualified exports.
I think the reason it was not added before is down to the fact that modules don't really export other modules. They just export other modules contents. (Also it was a deliberately conservative extension.)
Exporting qualified names doesn't really change that, we're just exporting the contents of a module but with qualified names.
This seems like quite a significant change from the way the module system works at the moment (not that this is a bad thing). Currently a module can only export "entities", i.e. the things that names refer to. It is completely up to the importing module to decide what names to introduce for the imported entities. With this suggestion a module would have to export not only entities but also hints instructing the importing module how to name things. It looks like this could work without too much difficulty. Presumably the qualified names introduced by the importing moudle should be computed by joining the "as" clause of the import with the hint that came along with the entity (if any). We probably don't want to have multiple hints, so that each entity can have at most one hint associated with it. -Iavor
participants (8)
-
Andre Pang -
Benjamin Franksen -
Duncan Coutts -
Duncan Coutts -
Gour -
Iavor Diatchki -
Iavor S. Diatchki -
Sebastian Sylvan