Export template haskell generated definitions - haskell

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.

Related

Why "The data constructors of ‘Path’ are not all in scope" when imported with `Path (..)`

The current package imports indirectly the constructor Path(..) which, in modules closer in the chain of imports to the source, can be used to derive Read but when I try to use it later in a standalone deriving clause I get
• Can't make a derived instance of ‘Read (Path Abs Dir)’:
The data constructors of ‘Path’ are not all in scope
so you cannot derive an instance for it
• In the stand-alone deriving instance for ‘Read (Path Abs Dir)’
The module code gives no error and imports Path(..). What is missing in the import?
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
module Uniform.Convenience.StartApp(
module Uniform.Convenience.StartApp
) where
import UniformBase
import UniformBase (Path(..), Read(..))
data Aby = Aby44 Int (Path Abs Dir) deriving (Eq, Ord, Show )
deriving instance Read (Path Abs Dir)
A minimal version of this looks like:
module A (Foo(Exported)) where
data Foo = Exported | Not
module B where
import A(Foo(..))
Since Not is not exported from A, it cannot be imported, even by the syntax import A(Foo(..)). Only Exported will be in scope in B.
Something similar is happening to you: somewhere along the import chain, one of the modules has chosen not to export at least one of the constructors of Path, for one reason or another (probably in part to prevent Read instances ;-).
You say:
in the case in discussion, the imports and exports are always all what a module exports (as you can see in the shown module, which exports module xx).
You may find this excerpt of the section of the Report on exports interesting:
The form “module M” names the set of all entities that are in scope with both an unqualified name “e” and a qualified name “M.e”.
In particular, consider
module A (module A) where data Foo = Exported | Not
module B (module A) where import A(Foo(Exported))
module C where import B(Foo(..))
Again, in module C the Not constructor will not be in scope. This time, it is because it was not imported by B, and therefore not exported by it.
Eventually I found the reason Path was not available in the module that imported it. It was shadowed in an intermediate module which imported and exported it wholly (somewhat similar to what #DanielWagner suggested):
module UniformBase
( module Uniform.FileIO
, Generic
, Read
, Path (..)
) where
import Uniform.FileIO
I had inserted Path (..) there for good measure, to insure it is REALLY exported, and the effect was exactly the opposite. Path (..) was found somehere and replaced the one I wanted to export. After removing Path (..) from the export list the Path imported with Uniform.FileIO was available.
Subtle error, hard to understand (where did the wrong Path(..) come from ?) and time consuming to identify (the caching of cabal build did not help!). I observed that the error disappeared when I imported Uniform.FileIO directly and in addition to `UniformBase'.

What does it mean when a Haskell module doesn't declare any exports?

I just ran into a Haskell module that appears not to export anything. Schwifty/Swift/M105/Types.hs:
module Schwifty.Swift.M105.Types where
There are other modules in the project that import it.
import Schwifty.Swift.M105.Types
I thought Haskell modules always had to declare their exports. What does it mean when you don't?
You have to distinguish
an empty export list (module Foo () where) and
no export list at all (module Foo where).
The empty export list means: Export no value or type definitions. However, the module still exports all instance declarations from the module itself, and from all imported modules, so modules with empty export lists can be useful.
No export list at all means: Export all value and type definitions made in the module itself. (And all instance declarations, too, of course).
From A Gentle Introduction to Haskell, Version 98:
If the export list following the module keyword is omitted, all of the names bound at the top level of the module would be exported.

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 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

GHC refuses to export qualified modules

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.

Resources