diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Clinton Mead (c) 2017
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Clinton Mead nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/gen-imports.cabal b/gen-imports.cabal
new file mode 100644
--- /dev/null
+++ b/gen-imports.cabal
@@ -0,0 +1,31 @@
+name:                gen-imports
+version:             0.1.0.0
+synopsis:            Code to generate instances for the package "ghc-instances"
+description:
+  Functions in this package look at the hackage database to get all the public modules of packages.
+
+  It then creates Haskell files containing each module as an import statement.
+
+  It's primary purpose is to produce files for the package
+  [ghc-instances](https://hackage.haskell.org/package/ghc-instances).
+  See that package for the motivation behind this.
+homepage:            https://github.com/clintonmead/gen-imports#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Clinton Mead
+maintainer:          clintonmead@gmail.com
+copyright:           Copyright: (c) 2017 Clinton Mead
+category:            Web
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Distribution.Hackage.Imports.Generate
+  build-depends:       base >= 4.7 && < 5, hackage-db < 2, Cabal, containers, pretty, bytestring, filepath
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+
+source-repository head
+  type:     git
+  location: https://github.com/clintonmead/gen-imports
diff --git a/src/Distribution/Hackage/Imports/Generate.hs b/src/Distribution/Hackage/Imports/Generate.hs
new file mode 100644
--- /dev/null
+++ b/src/Distribution/Hackage/Imports/Generate.hs
@@ -0,0 +1,136 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+module Distribution.Hackage.Imports.Generate where
+
+import Data.ByteString (ByteString)
+
+import Distribution.Hackage.DB (Hackage, Version, readHackage)
+import Distribution.PackageDescription (
+  GenericPackageDescription(packageDescription, condLibrary),
+  PackageDescription(library),
+  Library(exposedModules),
+  CondTree(CondNode, condTreeData)
+  )
+import Distribution.ModuleName (ModuleName)
+import qualified Distribution.ModuleName
+import Distribution.Version (Version(versionBranch))
+import Distribution.Text (disp)
+import qualified Data.Map.Lazy
+import Control.Arrow (second)
+import Text.PrettyPrint (Doc, text, ($+$), render)
+import GHC.Exts (sortWith, Down(Down))
+import Data.Monoid ((<>), mempty)
+import Data.Foldable (foldl')
+import System.FilePath (FilePath, (</>))
+import Data.String (fromString)
+import Data.Char (toUpper)
+import Data.Foldable (traverse_)
+import Data.List (intercalate)
+import Debug.Trace (traceShowId)
+
+type PackageName = String
+
+class ToString a where
+  toString :: a -> String
+
+instance ToString String where
+  toString = id
+
+stringToFilePath :: String -> FilePath
+stringToFilePath = id
+
+getExposedModules :: GenericPackageDescription -> [ModuleName]
+getExposedModules gpd = let
+  libs1 = case library (packageDescription gpd) of
+    Nothing -> []
+    Just l -> exposedModules l
+  libs2 = case condLibrary gpd of
+    Nothing -> []
+    Just (CondNode{condTreeData=l}) -> exposedModules l
+  in
+    libs1 ++ libs2
+
+getExposedModulesAllVersions :: Hackage -> PackageName -> [(Version, [ModuleName])]
+getExposedModulesAllVersions hackage pn = case Data.Map.Lazy.lookup pn hackage of
+  Nothing -> []
+  Just gpdm -> (second getExposedModules) <$> Data.Map.Lazy.toList gpdm
+
+genImportList :: (ModuleName -> Doc) -> ModuleName -> PackageName -> [(Version, [ModuleName])] -> Doc
+genImportList f moduleName packageName l = languageCpp $+$ moduleHeader $+$ guard $+$ body $+$ endIf $+$ "#endif" where
+  languageCpp = "{-# LANGUAGE CPP #-}"
+  guard = "#ifdef MIN_VERSION_" <> packageNameDoc
+  packageNameDoc = text (replace_dash <$> toString packageName)
+  moduleHeader = "module " <> disp moduleName <> " where"
+  endIf = case l of
+    [] -> mempty
+    _ -> "#endif"
+  body = (foldl' ($+$) mempty $ zipWith g ("#if":(repeat "#elif")) (sortWith Down l))
+  g macro (version, module_list) = preprocessorLine $+$ modules where
+    preprocessorLine = macro <> " MIN_VERSION_" <> packageNameDoc <> "(" <> v1 <> "," <> v2 <> "," <> v3 <> ")"
+    modules = foldl' ($+$) mempty (f <$> module_list)
+    [v1, v2, v3] = (text . show) <$> (take 3 (versionBranch version ++ [0..]))
+
+
+genImportListFromHackage :: Hackage -> ModuleName -> PackageName -> Doc
+genImportListFromHackage hackage moduleName packageName = genImportList toImportLine moduleName packageName (getExposedModulesAllVersions hackage packageName) where
+
+toImportLine :: ModuleName -> Doc
+toImportLine mn = "import " <> disp mn <> " ()"
+
+writeImportListToFile :: Hackage -> FilePath -> [String] -> PackageName  -> IO ()
+writeImportListToFile hackage basePath baseModuleStrList packageName =
+  writeFile moduleFileName $ render (genImportListFromHackage hackage moduleName packageName) where
+    capitalisedPackageName = let (s:ss) = toString packageName in fromString (((toUpper s):(replace_dash <$> ss)))
+    capitalisedPackageFileName = capitalisedPackageName <> ".hs"
+    moduleFileName = (foldl' (</>) basePath (map stringToFilePath baseModuleStrList)) </> capitalisedPackageFileName
+    moduleName = Distribution.ModuleName.fromString ((intercalate "." baseModuleStrList) <> "." <> capitalisedPackageName)
+
+replace_dash :: Char -> Char
+replace_dash c = case c of
+  '-' -> '_'
+  x -> x
+
+writeImportListsToDir :: Foldable f => FilePath -> [String] -> f PackageName -> IO ()
+writeImportListsToDir basePath baseModuleStrList packageNames = do
+  hackage <- readHackage
+  traverse_ (writeImportListToFile hackage basePath baseModuleStrList) packageNames
+
+writeGHCPackageImportListsToDir :: FilePath -> [String] -> IO ()
+writeGHCPackageImportListsToDir basePath baseModuleStrList = writeImportListsToDir basePath baseModuleStrList ghcPackages
+
+ghcPackages :: [PackageName]
+ghcPackages = [
+  "array",
+  "base",
+  "binary",
+  "bytestring",
+  "Cabal",
+  "containers",
+  "deepseq",
+  "directory",
+  "filepath",
+  "ghc",
+  "ghc-boot",
+  "ghc-compact",
+  "ghc-prim",
+  "haskell98",
+  "haskell2010",
+  "hoopl",
+  "hpc",
+  "old-locale",
+  "old-time",
+  "integer-gmp",
+  "process",
+  "template-haskell",
+  "time",
+  "unix",
+  "Win32"
+  ]
+
+{-
+getExposedModulesAllVersionsIO :: PackageName -> IO [(Version, [ModuleName])]
+getExposedModulesAllVersionsIO pn = do
+  hackage <- readHackage
+  pure $ getExposedModulesAllVersions hackage pn
+-}
