GHC refuses to export qualified modules - haskell

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?

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.

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.

Related

Haskell: Qualified name in binding position?

I have a file test.hs with the following code:
Mp1.gcd a =a
When I compile it, there is this error:
"Qualified name in binding position:Mp1.gcd Failed, modules loaded:none"
I use Mp1.gcd because the official API has "gcd".
Is this problem about my naming conventions? How can I fix it?
You can define it without qualifying it at all:
gcd a = {- ... -}
Then qualify it in your export list:
module MyModule (MyModule.gcd) where
Alternatively, remove the possibility for conflict altogether by excluding Prelude's gcd:
import Prelude hiding (gcd)

Haskell library import syntax

Sorry for the very basic question: In GHCi, is there a difference between import Library.Name and :m +Library.Name? They seem equivalent, but I assume there's a reason for the alternative syntax.
You're right that import Module and :module + Module are identical, but there are a few reasons for the :module (henceforth abbreviated :m) syntax.
It's older. GHCi really used to just be the inside of an IO do block; now it supports every part of the language, so we can do imports. (It looks like GHCi 6.6.x didn't support import, but GHCi 6.8.1 did; we didn't get full support for top-level declarations until GHCi 7.4.1.)
It lets you import multiple modules at once. :m + M1 M2 M3 is the same as writing import M1, import M2, and import M3 each on a new line.
It lets you un-import modules: :m - M will remove M's contents from what's currently in scope at the prompt.
It lets you import an interpreted module so that you can see the whole scope. This is what happens when you :load File.hs; you find that you're in the module *File, and can e.g. see everything that File imports and even everything that it doesn't export. If you have an interpreted module MI loaded, then you can use :m + M1 *MI M3 to bring M1 and M2 into scope the ordinary way, and MI into scope the special way.
For completeness, though, import syntax does offer us three things that :m doesn't:
Qualified imports. It's much nicer to be able to do import qualified Data.Map as M and use M.lookup than to have to do Data.Map.lookup or suffer ambiguity errors. (Note that every package that's installed is available fully qualified in GHCi, so import qualified Module alone buys you nothing.)
Import lists. Even if I have the functions from Data.Map qualified with M, I can still do import Data.Map (Map) to just bring the type into scope unqualified.
Import hiding. The reverse of the above; maybe I'm writing my own sorting routine, so I can do import Data.List hiding (sort).
You can also check out §2.4.5, "What's really in scope at the prompt?", in the GHC (7.6) user's guide.
You would include import in the source code, which is more general, whereas :m is a ghci - specific command (for convenience).
You can use ghci> :m + Module1 ... ModuleN to load multiple modules. Use - instead of + to unload the module. Because ghci is interactive, I'd stick to :m, unless your workflow is rather: edit your .hs file, save it, and reload it. Then the import would be more suitable (and has more features e.g. qualified imports).
The import directive would also work if you later decide to compile the program using for example ghc. You can selectively import only specific functions: import Data.List (sort) would import only sort, so is pollutes the namespace less.

import qualified in GHCI

Does it is possible to use the equivalent of "import qualified" in GHCI with our OWN module? Something like :m + qualified Data.List which of course doesn't work.
Thanks.
Just type import qualified Data.Text or import qualified Data.Text as T inside ghci, just as you would do inside your code.
I don't know of a pretty way to do what you want, but you could fake it with something like this:
First, use :load My/Module.hs to load your module.
Use :module - My.Module to bring it out of scope.
(Optional.) Use import qualified My.Module as MM to bring it into scope qualified.
Every module that GHCi knows about is automatically available fully qualified, so after step 2, My.Module.value will work fine. Step 3 is only necessary if you want to use a shorter prefix.
If you want to load multiple files at once, :load can do that too;
:load My/Module1.hs My/Module2.hs ... My/ModuleN.hs
will work fine. It will put you in the scope of *My.Module1, and then My.Module2 … My.ModuleN will all be available fully qualified as mentioned above.
For more about GHCi, you can always check the GHC User's Guide, Ch. 2: "Using GHCi"; particularly relevant sections are §2.2, "Loading source files" and §2.4.5, "What's really in scope at the prompt?".

Haskell how to hide (exclude) a function from module without explicitly listing all the non hidden functions?

I have a Haskell module, and I’d like it to export all objects declared in its file except for one specific function local_func.
Is there a cleaner way to achieve this than by writing an export list explicitly listing all the other declarations (and carefully keeping this list up-to-date for all eternity)?
In other words, I’d like an analogue of import MyModule hiding (local_func), but specified in the exporting module rather that at import time.
As far as I'm aware there is not currently a way to do this.
What I usually end up doing is having a central module that re-exports important things as a convenient way to import everything that is necessary while not hiding anything in the modules defining these things (which in some cases - that you probably won't foresee! - makes it easier for your users to modify things in your module).
To do this use the following syntax:
-- |Convenient import module
module Foo.Import (module All) where
-- Import what you want to export
import Foo.Stuff as All hiding (local_func)
-- You can import several modules into the same namespace for this trick!
-- For example if using your module also requires 'decode' from "Data.Aeson" you can do
import Data.Aeson as All (decode)
You have now conveniently exported these things.
Unfortunately not.
One could imagine a small syntactic addition which would allow the kind of thing you're asking for. Right now it's possible to write:
module M (module M) where
foo = quux
quux = 1+2
You can explicitly export the whole module. But suppose we were to add syntax such that it was possible to hide from that module. Then we would be able to write like this:
module M (module M hiding (quux)) where
foo = quux
quux = 1+2

Export template haskell generated definitions

My module contains definitions, part of which are exported (in module clause). I want to export Template Haskell-generated declarations too. But since there is seemingly no way to modify module clause with TH, I cannot do this.
Is it possible to specify that TH-generated declarations should be exported at all? Or maybe there are other ways to do this?
You need to export the names of the generated TH declarations. For example, if you have a TH function that generates a data B = C | D declaration, you need to simply export module Mymodule (B(C,D)) where ....
If you don't specify an export list, all declarations in that module will be exported. What you can do as a little trick is to put all of your generated TH functions in one module, and then reexport that module:
{-# LANGUAGE TemplateHaskell #-}
-- Put all of the generated stuff in one module
module Bla.Generated where
generateAFunctionCalled "foo"
generateAFunctionCalled "bar"
-- Re-export the generated module
module Bla (module Bla.Generated) where
import qualified Bla.Generated
This has the disadvantage that you can't put haddock documentation for generated functions, but that's not something you usually do anyways.

Categories

Resources