Opened 8 years ago

Last modified 6 months ago

#1475 new feature request

Adding imports and exports with Template Haskell

Reported by: igloo Owned by:
Priority: normal Milestone:
Component: Template Haskell Version: 6.8.2
Keywords: Cc: ganesh.sittampalam@…, alfonso.acosta@…, mjm2002@…, Deewiant, merehap, ivan.perez@…,…, campersander@…, silvio.frischi@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


(wished for by Adrian Hey in

It would be useful to be able to add module exports with TH, although I'm not sure exactly how it would be done. Perhaps something like

$( do n <- newName "foo"
      let d = funD n ...
      addExport (varE n)
      return [d]

but at the point we call addExport the typechecker doesn't know that there will be a declaration for the name.

Less useful, as TH names include the package and module of the name's definition, is the ability to add module imports. However, this can still be used to get a kind of dynamic binding effect, either with mkName's names or plain Haskell code, e.g.:

$( addImport (if ... then '''Data.ByteString else '''Data.ByteString.Lazy)
             (mkName "BS") )

foo :: BS.ByteString
foo = BS.append ...

(we'd actually probably want a datatype that mirrors Haskell import decls more closely).

Change History (21)

comment:1 Changed 8 years ago by guest

  • Cc ganesh.sittampalam@… added

comment:2 Changed 8 years ago by igloo

  • Milestone changed from 6.8 branch to _|_

comment:3 Changed 8 years ago by fons

  • Cc alfonso.acosta@… added

comment:4 Changed 8 years ago by m4dc4p

  • Version changed from 6.6.1 to 6.8.2

I would love for template haskell to be able to add imports. I am using haskelldb to write strongly-typed SQL queries. These queries depend on a compile time representation of the database schema. That representation is obtained by running a program which produces Haskell source describing a given set of tables, etc. If TH could write import statements, I could dynamically generated my modules and then import them in one go. My queries would always be compiled against the most recent schema! It would be a great feature to have.

comment:5 Changed 8 years ago by simonpj

Whoa! Can you give more detail on your example? At the moment you definitely can't write a TH function that generates a Haskell module, compiles it, and imports it. You can generate those definitions in the current module though.

Remember too that a TH definition can mention things in scope, and those things do not need to be imported where the TH function is called. Example

module T(f) where
  import List
  f = [| null |]

module Foo where
  import T
  h = $f

Here $f expands to null, but you do not need to import List in module Foo. In fact $f expands to Data.List.null, a kind of absolute reference to null.

As the intro to this ticket says, TH-generated imports are really only useful for a form of dynamic binding.


comment:6 Changed 8 years ago by m4dc4p

I don't need TH to dynamically create a module, compile it and import it in one go (though my message does imply that). Just being able to add import statements would be enough. Continuing with haskelldb, "table" definitions can be stored in separate modules. For example, If I have two tables, customers and orders, then they would normally be in the modules Acme.Customers and Acme.Orders. If I have a third module which defines all my queries, Acme.Queries, then I import the two tables as:

  module Acme.Queries where

  import qualified Acme.Customers as Customers
  import qualified Acme.Orders as Orders

Notice the qualified imports - those are necessary to avoid name clashes between the two modules (e.g., imagine if both tables have an ID column).

As I add more tables, I need to add more import statements. Maybe I have a registration table:

  import qualified Acme.Registration as Registration

And so on, adding more and more clutter. Right now I have a file that imports about 15 "tables" and it's painful. I'd much rather have TH generate the import definition for me. For example:

  module Acme.Queries where

  $(importTables "Acme", ["Registration", "Customers", "Orders"])

This becomes more important when you consider that I am trying to create a tool for other developers in my organization to use. They don't know Haskell, and I'd rather they didn't know they are learning Haskell until it's too late. Having to add these import statements would be a barrier for them.

comment:7 Changed 7 years ago by simonmar

  • Architecture changed from Unknown to Unknown/Multiple

comment:8 Changed 7 years ago by simonmar

  • Operating System changed from Unknown to Unknown/Multiple

comment:9 Changed 7 years ago by morrow

  • Cc mjm2002@… added

comment:10 Changed 7 years ago by Deewiant

  • Cc Deewiant added

comment:11 Changed 6 years ago by merehap

  • Cc merehap added
  • Type of failure set to None/Unknown

comment:12 Changed 4 years ago by SimonHengel

Being able to generate import statements with TH would be awesome.

Here is my use case.

Say I have a directory that contains several modules with tests (using hspec as an example, and assuming that each module exports some spec):


Then I'd like to generate a Main.hs by writing something like this:

-- test/Main.hs
{-# LANGUAGE TemplateHaskell #-}

import Test.Hspec.TH (autoRun)


Which should expand to.

-- test/Main.hs
import qualified FooSpec
import qualified BarSpec
import qualified BazSpec

main = hspec $ do
  describe "Foo" FooSpec.spec
  describe "Bar" BarSpec.spec
  describe "Baz" BazSpec.spec

comment:13 Changed 4 years ago by GregWeber

I have a similar use case for my shell scripting library called shelly, but I am more focused on wanting to add language pragmas and default(Text).

comment:14 Changed 3 years ago by ivan.perez

  • Cc ivan.perez@… added

I have a use case very similar to Simon Hengel's in my hails library. I am currently generating these imports using a custom Setup.hs and an ad hoc auxiliary tool.

comment:15 Changed 3 years ago by liyang

  • Cc… added

comment:16 Changed 22 months ago by charmander

  • Cc campersander@… added

comment:17 Changed 19 months ago by yokto

  • Cc silvio.frischi@… added

comment:18 Changed 18 months ago by simonpj

Warning: allowing splicing of imports would make it much harder to track dependencies between modules, so things like ghc --make would become harder. I've only just realised this.

So tread carefully here!


comment:19 Changed 18 months ago by SimonHengel

Just because I've been pushing for this in the past, I solved my use case in a different way.

For me closing this as won't fix would be ok.

comment:20 Changed 18 months ago by goldfire

I still want it. singletons generates gobs of boilerplate, some of which it is important to export. It's not terribly hard for users to write the export lists manually, but it's just more boilerplate that would be nice to automate.

However, for my use case, I care only about TH writing to export lists, not import lists. TH-controlled export lists wouldn't hit the problem SPJ points out in comment:18.

comment:21 Changed 6 months ago by cdupont

I have also a use case for it. I need to generate imports that are extracted from GIT history. Using TH to do that would be elegant as I could extract the file and splice in the module name in the import list at the same time.

Note: See TracTickets for help on using tickets.