18
votes

I want to write a module which re-exports some module it had imported qualified. Something like this:

module Foo.A
  ( module Foo.B
  , module Foo.C
  ) where
import qualified Foo.B
import qualified Foo.C

-- bunch of code using Foo.B and Foo.C here

This looks like it ought to work; however, GHC prints warnings about the exports:

Foo/A.hs:2:5:
    Warning: the export item `module Foo.B' exports nothing

Foo/A.hs:3:5:
    Warning: the export item `module Foo.C' exports nothing

And GHCI refuses to load exports from them.

I can solve this by making the imports unqualified, but then naming conflicts are likely to arise between those imports and the main module code.

Is there any way to make GHC export these modules?

2

2 Answers

13
votes

No, that isn't just a limitation of GHC, it's the way import and export is designed to work in Haskell.

A module only has control of its own namespace - it can't affect what people can see from other namespaces. A module "re-export" is just a shorthand to say "export all of the symbols in my own namespace that happen to have been imported here from that other module". But symbols that you imported qualified aren't really in your own namespace.

If you want to export two different symbols that have the same name, you won't be able to do it from one module. Split the module into two, and export each version from a different module.

7
votes

This limitation is also a convenience when the importing module is meant to re-declare some names in the imported module, based on declarations of a qualified import. For instance:

module MyPrelude (succ, module Prelude) where

import qualified Prelude as P (succ)
import Prelude hiding (succ)

succ :: ...
succ = ... P.succ ...

this idiom would be really hard to express without a lot of verbosity otherwise. Also, ask your self "would this make sense without hierarchical modules?". If not, then this is very ghc specific, and what is actually going on when referencing a hierarchical module name from an expression is not hierarchical at all.

As to why you are able to reexport individual symbols qualified by some module name you did not import, that seems like a kludge to get heirarchical modules to work heirachically in ghc. Gaining Foo.B qualified symbols when importing Foo.A is magical, and I think its because The name Foo is no more an actual heirachical ancestor than Foo.A, but the intended use of exporting things with alternate qualification is in cases where its used from Foo. I don't think this behavior makes sense at all without GHC extensions, so I am going to take a wild guess that its GHC specific.