diff --git a/Language/Haskell/Modules.hs b/Language/Haskell/Modules.hs
--- a/Language/Haskell/Modules.hs
+++ b/Language/Haskell/Modules.hs
@@ -66,6 +66,10 @@
 --                  (ModuleName \"Language\/Haskell\/Modules\/Internal.hs\") >>
 --      mergeModules [ModuleName \"Language.Haskell.Modules.Common\", ModuleName \"Tmp\"]
 --                   (ModuleName \"Language.Haskell.Modules.Common\")@
+--
+-- * Split a module where one of the result modules needs to import the instances:
+--
+--  @runCleanT $ putModule (ModuleName \"Main\") >> extraImport (ModuleName \"Main.GetPasteById\") (ModuleName \"Main.Instances\") >> splitModuleDecls \"Main.hs\"@
 module Language.Haskell.Modules
     (
     -- * Entry points
@@ -87,9 +91,13 @@
     , modifyTestMode
     , modifyDirs
     , putDirs
+    , extraImport
     -- * Progress reporting
     , noisily
     , quietly
+    -- * Re-Exports from haskell-src-exts
+    , ModuleName(ModuleName)
+    , Name(Ident, Symbol)
     -- * Helper functions
     , modulePathBase
     , findHsModules
@@ -97,12 +105,12 @@
     , withCurrentDirectory
     ) where
 
+import Language.Haskell.Exts (ModuleName(..), Name(..))
 import Language.Haskell.Modules.Common (withCurrentDirectory)
 import Language.Haskell.Modules.Imports (cleanImports)
-import Language.Haskell.Modules.Internal (CleanT, MonadClean, runCleanT)
 import Language.Haskell.Modules.Merge (mergeModules)
 import Language.Haskell.Modules.ModuVerse (findModule, modifyExtensions, putModule)
-import Language.Haskell.Modules.Params (modifyDryRun, modifyHsFlags, modifyRemoveEmptyImports, modifyTestMode)
+import Language.Haskell.Modules.Params (CleanT, extraImport, modifyDryRun, modifyHsFlags, modifyRemoveEmptyImports, modifyTestMode, MonadClean, runCleanT)
 import Language.Haskell.Modules.SourceDirs (modifyDirs, modulePathBase, SourceDirs(putDirs))
 import Language.Haskell.Modules.Split (defaultSymbolToModule, splitModule, splitModuleDecls)
 import Language.Haskell.Modules.Util.QIO (noisily, quietly)
diff --git a/Language/Haskell/Modules/Common.hs b/Language/Haskell/Modules/Common.hs
--- a/Language/Haskell/Modules/Common.hs
+++ b/Language/Haskell/Modules/Common.hs
@@ -1,14 +1,32 @@
-{-# LANGUAGE BangPatterns, FlexibleInstances, PackageImports, ScopedTypeVariables #-}
+{-# LANGUAGE BangPatterns, FlexibleContexts, FlexibleInstances, PackageImports, ScopedTypeVariables #-}
 {-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
 module Language.Haskell.Modules.Common
     ( groupBy'
     , withCurrentDirectory
+    , ModuleResult(..)
+    , doResult
+    , reportResult
+    , fixExport
     ) where
 
-import "MonadCatchIO-mtl" Control.Monad.CatchIO (bracket, MonadCatchIO)
-import Control.Monad.Trans (liftIO)
+import Control.Exception.Lifted as IO (bracket, catch, throw)
+import Control.Monad.Trans (MonadIO, liftIO)
+import Control.Monad.Trans.Control (MonadBaseControl)
 import Data.List (groupBy, sortBy)
+import Data.Monoid ((<>))
+import Data.Sequence as Seq (Seq, (|>))
+import qualified Language.Haskell.Exts.Annotated as A (ExportSpec)
+import Language.Haskell.Exts.Annotated.Simplify (sExportSpec)
+import Language.Haskell.Exts.Pretty (prettyPrint)
+import qualified Language.Haskell.Exts.Syntax as S (ExportSpec(EModuleContents), ModuleName(..))
+import Language.Haskell.Modules.ModuVerse (delName, ModuVerse, putModuleAnew, unloadModule)
+import Language.Haskell.Modules.SourceDirs (modulePath, PathKey(..), APath(..))
+import Language.Haskell.Modules.Util.DryIO (createDirectoryIfMissing, MonadDryRun(..), removeFileIfPresent, replaceFile, tildeBackup)
+import Language.Haskell.Modules.Util.QIO (MonadVerbosity(..), qLnPutStr, quietly)
+import Prelude hiding (writeFile, writeFile)
 import System.Directory (getCurrentDirectory, setCurrentDirectory)
+import System.FilePath (dropExtension, takeDirectory)
+import System.IO.Error (isDoesNotExistError)
 
 -- | Convert a compare function into an (==)
 toEq :: Ord a => (a -> a -> Ordering) -> (a -> a -> Bool)
@@ -21,8 +39,81 @@
 groupBy' :: Ord a => (a -> a -> Ordering) -> [a] -> [[a]]
 groupBy' cmp xs = groupBy (toEq cmp) $ sortBy cmp xs
 
-withCurrentDirectory :: MonadCatchIO m => FilePath -> m a -> m a
+withCurrentDirectory :: (MonadIO m, MonadBaseControl IO m) => FilePath -> m a -> m a
 withCurrentDirectory path action =
     bracket (liftIO getCurrentDirectory >>= \ save -> liftIO (setCurrentDirectory path) >> return save)
             (liftIO . setCurrentDirectory)
             (const action)
+
+data ModuleResult
+    = Unchanged S.ModuleName PathKey
+    | ToBeRemoved S.ModuleName PathKey
+    | JustRemoved S.ModuleName PathKey
+    | ToBeModified S.ModuleName PathKey String
+    | JustModified S.ModuleName PathKey
+    | ToBeCreated S.ModuleName String
+    | JustCreated S.ModuleName PathKey
+    deriving (Show, Eq, Ord)
+
+reportResult :: ModuleResult -> String
+reportResult (Unchanged _ key) = "unchanged " ++ show key
+reportResult (JustModified _ key) = "modified " ++ show key
+reportResult (JustCreated _ key) = "created " ++ show key
+reportResult (JustRemoved _ key) = "removed " ++ show key
+reportResult (ToBeModified _ key _) = "to be modified " ++ show key
+reportResult (ToBeCreated name _) = "to be created " ++ show name
+reportResult (ToBeRemoved _ key) = "to be removed: " ++ show key
+
+-- | It is tempting to put import cleaning into these operations, but
+-- that needs to be done after all of these operations are completed
+-- so that all the compiles required for import cleaning succeed.  On
+-- the other hand, we might be able to maintain the moduVerse here.
+doResult :: (ModuVerse m, MonadDryRun m, MonadVerbosity m) => ModuleResult -> m ModuleResult
+doResult x@(Unchanged name _) =
+    do quietly (qLnPutStr ("unchanged: " ++ prettyPrint name))
+       return x
+doResult (ToBeRemoved name key) =
+    do qLnPutStr ("removing: " ++ prettyPrint name)
+       let path = unPathKey key
+       unloadModule key
+       -- I think this event handler is redundant.
+       removeFileIfPresent path `IO.catch` (\ (e :: IOError) -> if isDoesNotExistError e then return () else throw e)
+       delName name
+       return $ JustRemoved name key
+
+doResult (ToBeModified name key text) =
+    do qLnPutStr ("modifying: " ++ prettyPrint name)
+       let path = unPathKey key
+       -- qLnPutStr ("modifying " ++ show path)
+       -- (quietly . quietly . quietly . qPutStr $ " new text: " ++ show text)
+       replaceFile tildeBackup path text
+       _key <- putModuleAnew name
+       return $ JustModified name key
+
+doResult (ToBeCreated name text) =
+    do qLnPutStr ("creating: " ++ prettyPrint name)
+       path <- modulePath "hs" name
+       -- qLnPutStr ("creating " ++ show path)
+       -- (quietly . quietly . quietly . qPutStr $ " containing " ++ show text)
+       createDirectoryIfMissing True (takeDirectory . dropExtension . unAPath $ path)
+       replaceFile tildeBackup (unAPath path) text
+       key <- putModuleAnew name
+       return $ JustCreated name key
+doResult x@(JustCreated {}) = return x
+doResult x@(JustModified {}) = return x
+doResult x@(JustRemoved {}) = return x
+
+-- | Update an export spec.  The only thing we might need to change is
+-- re-exports, of the form "module Foo".
+fixExport :: [S.ModuleName] -> S.ModuleName -> S.ModuleName
+          -> A.ExportSpec l -> String -> String -> String -> Seq String -> Seq String
+fixExport inNames outName thisName e pref s suff r =
+    case sExportSpec e of
+      S.EModuleContents name
+          -- when building the output module, omit re-exports of input modules
+          | thisName == outName && elem name inNames -> r
+          -- when building other modules, update re-exports of input
+          -- modules to be a re-export of the output module.
+          | elem name inNames -> r |> pref <> prettyPrint (S.EModuleContents outName) <> suff
+          -- Anything else is unchanged
+      _ -> r |> pref <> s <> suff
diff --git a/Language/Haskell/Modules/Imports.hs b/Language/Haskell/Modules/Imports.hs
--- a/Language/Haskell/Modules/Imports.hs
+++ b/Language/Haskell/Modules/Imports.hs
@@ -6,7 +6,7 @@
     ) where
 
 import Control.Applicative ((<$>))
-import "MonadCatchIO-mtl" Control.Monad.CatchIO as IO (bracket, catch, throw)
+import Control.Exception.Lifted as IO (bracket, catch, throw)
 import Control.Monad.Trans (liftIO)
 import Data.Char (toLower)
 import Data.Foldable (fold)
@@ -15,17 +15,17 @@
 import Data.Maybe (catMaybes, fromMaybe)
 import Data.Monoid ((<>), mempty)
 import Data.Sequence ((|>))
-import Data.Set as Set (empty, member, Set, singleton, toList, union, unions, fromList)
+import Data.Set as Set (empty, fromList, member, Set, singleton, toList, union, unions)
 import Language.Haskell.Exts.Annotated.Simplify as S (sImportDecl, sImportSpec, sModuleName, sName)
 import qualified Language.Haskell.Exts.Annotated.Syntax as A (Decl(DerivDecl), ImportDecl(..), ImportSpec(..), ImportSpecList(ImportSpecList), InstHead(..), Module(..), ModuleHead(..), ModuleName(..), QName(..), Type(..))
-import Language.Haskell.Exts.Extension (Extension(PackageImports))
 import Language.Haskell.Exts.Pretty (defaultMode, PPHsMode(layout), PPLayout(PPInLine), prettyPrintWithMode)
 import Language.Haskell.Exts.SrcLoc (SrcLoc(..), SrcSpanInfo)
 import qualified Language.Haskell.Exts.Syntax as S (ImportDecl(importLoc, importModule, importSpecs), ModuleName(..), Name(..))
+import Language.Haskell.Modules.Common (ModuleResult(..))
 import Language.Haskell.Modules.Fold (foldDecls, foldExports, foldHeader, foldImports)
-import Language.Haskell.Modules.Internal (markForDelete, ModuleResult(..), MonadClean(getParams), Params(hsFlags, removeEmptyImports, scratchDir, testMode))
-import Language.Haskell.Modules.ModuVerse (getExtensions, loadModule, findModule, modifyExtensions, ModuleInfo(..), moduleName, parseModule)
-import Language.Haskell.Modules.SourceDirs (modifyDirs, pathKey, PathKey(..), PathKey(unPathKey), SourceDirs(getDirs, putDirs))
+import Language.Haskell.Modules.ModuVerse (findModule, getExtensions, loadModule, ModuleInfo(..), moduleName, parseModule)
+import Language.Haskell.Modules.Params (markForDelete, MonadClean(getParams), Params(hsFlags, removeEmptyImports, scratchDir, testMode))
+import Language.Haskell.Modules.SourceDirs (modifyDirs, pathKey, APath(..), PathKey(..), PathKey(unPathKey), SourceDirs(getDirs, putDirs))
 import Language.Haskell.Modules.Util.DryIO (replaceFile, tildeBackup)
 import Language.Haskell.Modules.Util.QIO (qLnPutStr, quietly)
 import Language.Haskell.Modules.Util.SrcLoc (srcLoc)
@@ -60,7 +60,7 @@
 -- | Clean up the imports of a source file.
 cleanImports :: MonadClean m => [FilePath] -> m [ModuleResult]
 cleanImports paths =
-    do keys <- mapM pathKey paths >>= return . fromList
+    do keys <- mapM (pathKey . APath) paths >>= return . fromList
        dumpImports keys
        mapM (\ key -> parseModule key >>= checkImports) (toList keys)
 
@@ -71,25 +71,23 @@
     where
       dump =
           mapM (\ x -> case x of
-                         Removed _ _ -> return Nothing
+                         JustRemoved _ _ -> return Nothing
                          Unchanged _ _ -> return Nothing
-                         Modified _ key _ -> return (Just key)
-                         Created (S.ModuleName name) _ -> findModule name >>= return . fmap key_) results >>=
+                         JustModified _ key -> return (Just key)
+                         JustCreated name _ -> findModule name >>= return . fmap key_
+                         _ -> error $ "cleanResults - unexpected ModuleResult " ++ show x) results >>=
           dumpImports . fromList . catMaybes
       clean =
           mapM (\ x -> case x of
-                         Removed _ _ -> return x
+                         JustRemoved _ _ -> return x
                          Unchanged _ _ -> return x
-                         Modified _name key _ -> doModule key
-                         Created (S.ModuleName name) _ ->
-                             do mi <- findModule name
-                                let Just k = fmap key_ mi -- This is pretty sure to be a Just
-                                x' <- doModule k
-                                return $ toCreated x') results
+                         JustModified _name key -> doModule key
+                         JustCreated _name key -> doModule key >>= return . toCreated
+                         _ -> error $ "cleanResults - unexpected ModuleResult " ++ show x) results
       -- The cleaning may have turned a Created result into Modified,
       -- turn it back into Created.
-      toCreated (Modified name _key text) = Created name text
-      toCreated x@(Created {}) = x
+      toCreated (JustModified name key) = JustCreated name key
+      toCreated x@(JustCreated {}) = x
       toCreated _ = error "toCreated"
       -- Update the cached version of the now modified module and then
       -- clean its import list.
@@ -129,7 +127,6 @@
        markForDelete importsPath
        (ModuleInfo newImports _ _ _) <-
            withDot $
-             withPackageImportsExtension $
                (parseModule (PathKey importsPath)
                   `IO.catch` (\ (e :: IOError) -> liftIO (getCurrentDirectory >>= \ here ->
                                                           throw . userError $ here ++ ": " ++ show e)))
@@ -140,12 +137,6 @@
       isHiddenImport _ = False
 checkImports _ = error "Unsupported module type"
 
-withPackageImportsExtension :: MonadClean m => m a -> m a
-withPackageImportsExtension a =
-    bracket (getExtensions)
-            (modifyExtensions . const)
-            (\ saved -> modifyExtensions (const (PackageImports : saved)) >> a)
-
 withDot :: MonadClean m => m a -> m a
 withDot a =
     bracket (getDirs)
@@ -161,7 +152,7 @@
              (\ text' ->
                   qLnPutStr ("cleanImports: modifying " ++ show key) >>
                   replaceFile tildeBackup (unPathKey key) text' >>
-                  return (Modified (moduleName m) key text'))
+                  return (JustModified (moduleName m) key))
              (replaceImports (fixNewImports remove m oldImports (newImports ++ extraImports)) m)
 updateSource _ _ _ = error "updateSource"
 
diff --git a/Language/Haskell/Modules/Internal.hs b/Language/Haskell/Modules/Internal.hs
deleted file mode 100644
--- a/Language/Haskell/Modules/Internal.hs
+++ /dev/null
@@ -1,175 +0,0 @@
-{-# LANGUAGE FlexibleInstances, OverloadedStrings, PackageImports,
-             ScopedTypeVariables, StandaloneDeriving, UndecidableInstances #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-module Language.Haskell.Modules.Internal
-    ( runCleanT
-    , modifyParams
-    , markForDelete
-    , Params(..)
-    , CleanT
-    , MonadClean(getParams, putParams)
-    , ModuleResult(..)
-    , doResult
-    , fixExport
-    ) where
-
-import Control.Exception (SomeException, try)
-import "MonadCatchIO-mtl" Control.Monad.CatchIO as IO (catch, MonadCatchIO, throw)
-import Control.Monad.State (MonadState(get, put), StateT(runStateT))
-import Control.Monad.Trans (liftIO, MonadIO)
-import Data.Map as Map (empty, Map)
-import Data.Monoid ((<>))
-import Data.Sequence as Seq (Seq, (|>))
-import Data.Set as Set (empty, insert, Set, toList)
-import qualified Language.Haskell.Exts.Annotated as A (ExportSpec)
-import Language.Haskell.Exts.Annotated.Simplify (sExportSpec)
-import Language.Haskell.Exts.Pretty (prettyPrint)
-import qualified Language.Haskell.Exts.Syntax as S (ExportSpec(..), ImportDecl, ModuleName(..))
-import Language.Haskell.Modules.ModuVerse (delName, ModuVerse(..), moduVerseInit, ModuVerseState, putModuleAnew, unloadModule)
-import Language.Haskell.Modules.SourceDirs (PathKey(..), modulePath)
-import Language.Haskell.Modules.Util.DryIO (createDirectoryIfMissing, MonadDryRun(..), removeFileIfPresent, replaceFile, tildeBackup)
-import Language.Haskell.Modules.Util.QIO (MonadVerbosity(..), qLnPutStr, quietly)
-import Language.Haskell.Modules.Util.Temp (withTempDirectory)
-import Prelude hiding (writeFile)
-import System.Directory (removeFile)
-import System.FilePath (dropExtension, takeDirectory)
-import System.IO.Error (isDoesNotExistError)
-
--- | This contains the information required to run the state monad for
--- import cleaning and module spliting/mergeing.
-data Params
-    = Params
-      { scratchDir :: FilePath
-      -- ^ Location of the temporary directory for ghc output.
-      , dryRun :: Bool
-      -- ^ None of the operations that modify the modules will actually
-      -- be performed if this is ture.
-      , verbosity :: Int
-      -- ^ Increase or decrease the amount of progress reporting.
-      , hsFlags :: [String]
-      -- ^ Extra flags to pass to GHC.
-      , moduVerse :: ModuVerseState
-      -- ^ The set of modules that splitModules and catModules will
-      -- check for imports of symbols that moved.
-      , junk :: Set FilePath
-      -- ^ Paths added to this list are removed as the state monad
-      -- finishes.
-      , removeEmptyImports :: Bool
-      -- ^ If true, remove any import that became empty due to the
-      -- clean.  THe import might still be required because of the
-      -- instances it contains, but usually it is not.  Note that this
-      -- option does not affect imports that started empty and end
-      -- empty.
-      , extraImports :: Map S.ModuleName (Set S.ImportDecl)
-      -- ^ Deciding whether a module needs to be imported can be
-      -- difficult when instances are involved, this is a cheat to force
-      -- keys of the map to import the corresponding elements.
-      , testMode :: Bool
-      -- ^ For testing, do not run cleanImports on the results of the
-      -- splitModule and catModules operations.
-      } deriving (Eq, Ord, Show)
-
--- | An instance of MonadClean.
-type CleanT m = StateT Params m
-
-instance MonadClean m => ModuVerse m where
-    getModuVerse = getParams >>= return . moduVerse
-    modifyModuVerse f = modifyParams (\ p -> p {moduVerse = f (moduVerse p)})
-
-class (MonadIO m, MonadCatchIO m, Functor m) => MonadClean m where
-    getParams :: m Params
-    putParams :: Params -> m ()
-
-modifyParams :: MonadClean m => (Params -> Params) -> m ()
-modifyParams f = getParams >>= putParams . f
-
-instance (MonadCatchIO m, Functor m) => MonadClean (CleanT m) where
-    getParams = get
-    putParams = put
-
-instance MonadClean m => MonadVerbosity m where
-    getVerbosity = getParams >>= return . verbosity
-    putVerbosity v = modifyParams (\ p -> p {verbosity = v})
-
-instance MonadClean m => MonadDryRun m where
-    dry = getParams >>= return . dryRun
-    putDry x = modifyParams (\ p -> p {dryRun = x})
-
--- | Create the environment required to do import cleaning and module
--- splitting/merging.  This environment, StateT Params m a, is an
--- instance of MonadClean.
-runCleanT :: MonadCatchIO m => CleanT m a -> m a
-runCleanT action =
-    withTempDirectory "." "scratch" $ \ scratch ->
-    do (result, params) <- runStateT action (Params {scratchDir = scratch,
-                                                     dryRun = False,
-                                                     verbosity = 1,
-                                                     hsFlags = [],
-                                                     moduVerse = moduVerseInit,
-                                                     junk = Set.empty,
-                                                     removeEmptyImports = True,
-                                                     extraImports = Map.empty,
-                                                     testMode = False})
-       mapM_ (\ x -> liftIO (try (removeFile x)) >>= \ (_ :: Either SomeException ()) -> return ()) (toList (junk params))
-       return result
-
-markForDelete :: MonadClean m => FilePath -> m ()
-markForDelete x = modifyParams (\ p -> p {junk = insert x (junk p)})
-
-data ModuleResult
-    = Unchanged S.ModuleName PathKey
-    | Removed S.ModuleName PathKey
-    | Modified S.ModuleName PathKey String
-    | Created S.ModuleName String
-    deriving (Show, Eq, Ord)
-
--- | It is tempting to put import cleaning into these operations, but
--- that needs to be done after all of these operations are completed
--- so that all the compiles required for import cleaning succeed.  On
--- the other hand, we might be able to maintain the moduVerse here.
-doResult :: (ModuVerse m, MonadDryRun m, MonadVerbosity m) => ModuleResult -> m ModuleResult
-doResult x@(Unchanged _name key) =
-    do quietly (qLnPutStr ("unchanged: " ++ show key))
-       return x
-doResult x@(Removed name key) =
-    do quietly (qLnPutStr ("removed: " ++ show key))
-       let path = unPathKey key
-       unloadModule key
-       -- I think this event handler is redundant.
-       removeFileIfPresent path `IO.catch` (\ (e :: IOError) -> if isDoesNotExistError e then return () else throw e)
-       delName name
-       return x
-
-doResult x@(Modified m@(S.ModuleName name) key text) =
-    do quietly (qLnPutStr ("modified: " ++ show key))
-       path <- modulePath "hs" m
-       -- qLnPutStr ("modifying " ++ show path)
-       -- (quietly . quietly . quietly . qPutStr $ " new text: " ++ show text)
-       replaceFile tildeBackup path text
-       putModuleAnew name
-       return x
-
-doResult x@(Created m@(S.ModuleName name) text) =
-    do quietly (qLnPutStr ("created: " ++ name))
-       path <- modulePath "hs" m
-       -- qLnPutStr ("creating " ++ show path)
-       -- (quietly . quietly . quietly . qPutStr $ " containing " ++ show text)
-       createDirectoryIfMissing True (takeDirectory . dropExtension $ path)
-       replaceFile tildeBackup path text
-       putModuleAnew name
-       return x
-
--- | Update an export spec.  The only thing we might need to change is
--- re-exports, of the form "module Foo".
-fixExport :: [S.ModuleName] -> S.ModuleName -> S.ModuleName
-          -> A.ExportSpec l -> String -> String -> String -> Seq String -> Seq String
-fixExport inNames outName thisName e pref s suff r =
-    case sExportSpec e of
-      S.EModuleContents name
-          -- when building the output module, omit re-exports of input modules
-          | thisName == outName && elem name inNames -> r
-          -- when building other modules, update re-exports of input
-          -- modules to be a re-export of the output module.
-          | elem name inNames -> r |> pref <> prettyPrint (S.EModuleContents outName) <> suff
-          -- Anything else is unchanged
-      _ -> r |> pref <> s <> suff
diff --git a/Language/Haskell/Modules/Merge.hs b/Language/Haskell/Modules/Merge.hs
--- a/Language/Haskell/Modules/Merge.hs
+++ b/Language/Haskell/Modules/Merge.hs
@@ -4,11 +4,11 @@
     ( mergeModules
     ) where
 
-import Control.Monad as List (mapM, when)
-import "MonadCatchIO-mtl" Control.Monad.CatchIO as IO (catch)
+import Control.Monad as List (mapM, mapM_, when)
+import Control.Exception.Lifted as IO (catch)
 import Data.Foldable (fold)
 import Data.Generics (Data, everywhere, mkT, Typeable)
-import Data.List as List (intercalate, map, find)
+import Data.List as List (find, intercalate, map)
 import Data.Maybe (fromMaybe, isJust, mapMaybe)
 import Data.Monoid ((<>), mempty)
 import Data.Sequence as Seq ((<|), null, Seq, (|>))
@@ -18,10 +18,11 @@
 import Language.Haskell.Exts.Pretty (prettyPrint)
 import Language.Haskell.Exts.SrcLoc (SrcInfo)
 import qualified Language.Haskell.Exts.Syntax as S (ImportDecl(ImportDecl, importModule), ModuleName(..))
+import Language.Haskell.Modules.Common (doResult, fixExport, ModuleResult(..), reportResult)
 import Language.Haskell.Modules.Fold (echo, echo2, foldDecls, foldExports, foldHeader, foldImports, ignore, ignore2)
 import Language.Haskell.Modules.Imports (cleanResults)
-import Language.Haskell.Modules.Internal (doResult, fixExport, ModuleResult(..), MonadClean)
-import Language.Haskell.Modules.ModuVerse (getNames, ModuleInfo(..), parseModule, parseModuleMaybe, moduleName)
+import Language.Haskell.Modules.ModuVerse (getNames, ModuleInfo(..), moduleName, parseModule, parseModuleMaybe)
+import Language.Haskell.Modules.Params (MonadClean)
 import Language.Haskell.Modules.SourceDirs (modulePathBase, pathKey, pathKeyMaybe)
 import Language.Haskell.Modules.Util.QIO (qLnPutStr, quietly)
 
@@ -36,13 +37,10 @@
        quietly $
          do univ <- getNames
             let allNames = toList $ union univ (Set.fromList (outName : inNames))
-            results <- List.mapM (doModule inNames outName) allNames >>= List.mapM doResult >>= List.mapM reportResult
-            cleanResults results
-    where
-      reportResult x@(Modified _ key _) = qLnPutStr ("mergeModules: modifying " ++ show key) >> return x
-      reportResult x@(Created name _) = qLnPutStr ("mergeModules: creating " ++ show name) >> return x
-      reportResult x@(Removed _ key) = qLnPutStr ("mergeModules: removing " ++ show key) >> return x
-      reportResult x = return x
+            results <- List.mapM (doModule inNames outName) allNames
+            results' <- List.mapM doResult results
+            List.mapM_ (\ x -> qLnPutStr ("mergeModules: " ++ reportResult x)) results'
+            cleanResults results'
 
 -- Process one of the modules in the moduVerse and return the result.
 -- The output module may not (yet) be an element of the moduVerse, in
@@ -65,7 +63,7 @@
        when (isJust outInfo && notElem outName inNames) (error "mergeModules - if output module exist it must also be one of the input modules")
        case (thisName /= outName, List.find (\ x -> moduleName x == thisName) inInfo) of 
          (True, Just info) ->
-             return (Removed thisName (key_ info))
+             return (ToBeRemoved thisName (key_ info))
          _ ->
            let header =
                    fold (foldHeader echo2 echo (if thisName == outName
@@ -104,9 +102,9 @@
                text' = header <> exports <> imports <> decls in
            return $ case thisInfo of
                       Just (ModuleInfo {text_ = text, key_ = key}) ->
-                          if text' /= text then Modified thisName key text' else Unchanged thisName key
+                          if text' /= text then ToBeModified thisName key text' else Unchanged thisName key
                       Nothing ->
-                          Created thisName text'
+                          ToBeCreated thisName text'
            -- return $ if text' /= text then Modified thisName (key_ thisInfo) text' else Unchanged thisName (key_ thisInfo)
 doModule [] _ _ = error "doModule: no inputs"
 
diff --git a/Language/Haskell/Modules/ModuVerse.hs b/Language/Haskell/Modules/ModuVerse.hs
--- a/Language/Haskell/Modules/ModuVerse.hs
+++ b/Language/Haskell/Modules/ModuVerse.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP, FlexibleInstances, PackageImports, ScopedTypeVariables, StandaloneDeriving, UndecidableInstances #-}
+{-# LANGUAGE CPP, FlexibleContexts, FlexibleInstances, PackageImports, ScopedTypeVariables, StandaloneDeriving, UndecidableInstances #-}
 {-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
 module Language.Haskell.Modules.ModuVerse
     ( ModuleInfo(..)
@@ -24,18 +24,20 @@
     ) where
 
 import Control.Applicative ((<$>))
-import "MonadCatchIO-mtl" Control.Monad.CatchIO as IO (catch, MonadCatchIO, throw)
+import Control.Exception.Lifted as IO (catch, throw)
 import Control.Monad.Trans (liftIO, MonadIO)
+import Control.Monad.Trans.Control (MonadBaseControl)
 import Data.Map as Map (delete, empty, insert, keys, lookup, Map)
 import Data.Maybe (fromMaybe)
 import Data.Set as Set (fromList, Set)
 import qualified Language.Haskell.Exts.Annotated as A (Module(..), ModuleHead(..), ModuleName(..), parseFileWithComments)
 import Language.Haskell.Exts.Comments (Comment(..))
-import Language.Haskell.Exts.Extension (Extension)
-import qualified Language.Haskell.Exts.Parser as Exts (defaultParseMode, fromParseResult, ParseMode(extensions, parseFilename), ParseResult)
+import Language.Haskell.Exts.Extension (Extension(..))
+import Language.Haskell.Exts.Fixity (baseFixities)
+import qualified Language.Haskell.Exts.Parser as Exts (defaultParseMode, fromParseResult, ParseMode(extensions, parseFilename, fixities), ParseResult)
 import Language.Haskell.Exts.SrcLoc (SrcSpanInfo)
 import Language.Haskell.Exts.Syntax as S (ModuleName(..))
-import Language.Haskell.Modules.SourceDirs (modulePathBase, pathKey, PathKey(..), pathKeyMaybe, SourceDirs(..))
+import Language.Haskell.Modules.SourceDirs (modulePathBase, PathKey(..), Path(..), pathKey, SourceDirs(..))
 import Language.Haskell.Modules.Util.QIO (MonadVerbosity, qLnPutStr, quietly)
 import System.IO.Error (isDoesNotExistError, isUserError)
 
@@ -75,9 +77,18 @@
 moduVerseInit =
     ModuVerseState { moduleNames_ = Nothing
                    , moduleInfo_ = Map.empty
-                   , extensions_ = Exts.extensions Exts.defaultParseMode
+                   , extensions_ = Exts.extensions Exts.defaultParseMode ++ [StandaloneDeriving] -- allExtensions
                    , sourceDirs_ = ["."] }
 
+-- | From hsx2hs, but removing Arrows because it makes test case fold3c and others fail.
+hseExtensions :: [Extension]
+hseExtensions =
+    [ RecursiveDo, ParallelListComp, MultiParamTypeClasses, FunctionalDependencies, RankNTypes, ExistentialQuantification
+    , ScopedTypeVariables, ImplicitParams, FlexibleContexts, FlexibleInstances, EmptyDataDecls, KindSignatures
+    , BangPatterns, TemplateHaskell, ForeignFunctionInterface, {- Arrows, -} Generics, NamedFieldPuns, PatternGuards
+    , MagicHash, TypeFamilies, StandaloneDeriving, TypeOperators, RecordWildCards, GADTs, UnboxedTuples
+    , PackageImports, QuasiQuotes, TransformListComp, ViewPatterns, XmlSyntax, RegularPatterns ]
+
 getNames :: ModuVerse m => m (Set S.ModuleName)
 getNames = getModuVerse >>= return . Set.fromList . keys . fromMaybe (error "No modules in ModuVerse, use putModule") . moduleNames_
 
@@ -87,20 +98,23 @@
 putName :: ModuVerse m => S.ModuleName -> ModuleInfo -> m ()
 putName name info = modifyModuVerse (\ s -> s {moduleNames_ = Just (Map.insert name info (fromMaybe Map.empty (moduleNames_ s)))})
 
-putModule :: (ModuVerse m, MonadVerbosity m) => String -> m ()
-putModule name = pathKey (modulePathBase "hs" (S.ModuleName name)) >>= parseModule >>= putName (S.ModuleName name)
+putModule :: (ModuVerse m, MonadVerbosity m) => S.ModuleName -> m ()
+putModule name = pathKey (modulePathBase "hs" name) >>= parseModule >>= putName name
 
-putModuleAnew :: (ModuVerse m, MonadVerbosity m) => String -> m ()
-putModuleAnew name = pathKey (modulePathBase "hs" (S.ModuleName name)) >>= loadModule >>= putName (S.ModuleName name)
+putModuleAnew :: (ModuVerse m, MonadVerbosity m) => S.ModuleName -> m PathKey
+putModuleAnew name =
+    do key <- pathKey (modulePathBase "hs" name)
+       loadModule key >>= putName name
+       return key
 
-findModule :: (ModuVerse m, MonadVerbosity m) => String -> m (Maybe ModuleInfo)
-findModule name = pathKeyMaybe (modulePathBase "hs" (S.ModuleName name)) >>= parseModuleMaybe
+findModule :: (ModuVerse m, MonadVerbosity m) => S.ModuleName -> m (Maybe ModuleInfo)
+findModule name = pathKeyMaybe (modulePathBase "hs" name) >>= parseModuleMaybe
 
 delName :: ModuVerse m => S.ModuleName -> m ()
 delName name = modifyModuVerse (\ s -> s { moduleNames_ = Just (Map.delete name (fromMaybe Map.empty (moduleNames_ s)))
                                          , moduleInfo_ = Map.empty })
 
-class (MonadIO m, MonadCatchIO m, Functor m) => ModuVerse m where
+class (MonadIO m, MonadBaseControl IO m, Functor m) => ModuVerse m where
     getModuVerse :: m ModuVerseState
     modifyModuVerse :: (ModuVerseState -> ModuVerseState) -> m ()
 
@@ -155,5 +169,6 @@
 -- | Run 'A.parseFileWithComments' with the extensions stored in the state.
 parseFileWithComments :: ModuVerse m => FilePath -> m (Exts.ParseResult (A.Module SrcSpanInfo, [Comment]))
 parseFileWithComments path =
-    do exts <- getExtensions
-       liftIO (A.parseFileWithComments (Exts.defaultParseMode {Exts.extensions = exts, Exts.parseFilename = path}) path)
+    liftIO (A.parseFileWithComments mode path)
+    where
+      mode = Exts.defaultParseMode {Exts.extensions = hseExtensions, Exts.parseFilename = path, Exts.fixities = Just baseFixities}
diff --git a/Language/Haskell/Modules/Params.hs b/Language/Haskell/Modules/Params.hs
--- a/Language/Haskell/Modules/Params.hs
+++ b/Language/Haskell/Modules/Params.hs
@@ -1,16 +1,117 @@
 -- | Functions to control the state variables of 'MonadClean'.
-{-# LANGUAGE FlexibleInstances, OverloadedStrings, PackageImports, ScopedTypeVariables, UndecidableInstances #-}
+{-# LANGUAGE FlexibleContexts, FlexibleInstances, OverloadedStrings, PackageImports, ScopedTypeVariables, UndecidableInstances #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Language.Haskell.Modules.Params
-    ( modifyRemoveEmptyImports
+    ( Params(Params, dryRun, extraImports, hsFlags, junk, moduVerse,
+       removeEmptyImports, scratchDir, testMode, verbosity)
+    , CleanT
+    , MonadClean(getParams, putParams)
+    , modifyParams
+    , runCleanT
+    , markForDelete
+    , modifyRemoveEmptyImports
     , modifyHsFlags
     , modifyDryRun
     , modifyTestMode
+    , extraImport
     ) where
 
-import Language.Haskell.Modules.Internal (modifyParams, MonadClean, Params(dryRun, hsFlags, removeEmptyImports, testMode))
-import Prelude hiding (writeFile)
+import Control.Exception (SomeException, try)
+import Control.Monad.Trans.Control as IO (MonadBaseControl)
+import Control.Monad.State (MonadState(get, put), StateT(runStateT))
+import Control.Monad.Trans (liftIO, MonadIO)
+import Data.Map as Map (empty, Map, insertWith)
+import Data.Set as Set (empty, insert, Set, singleton, toList, union)
+import Language.Haskell.Exts.SrcLoc (SrcLoc(SrcLoc))
+import Language.Haskell.Exts.Syntax as S (ImportDecl(..), ModuleName)
+import Language.Haskell.Modules.ModuVerse (ModuVerse(..), moduVerseInit, ModuVerseState)
+import Language.Haskell.Modules.Util.DryIO (MonadDryRun(..))
+import Language.Haskell.Modules.Util.QIO (MonadVerbosity(..))
+import Language.Haskell.Modules.Util.Temp (withTempDirectory)
+import Prelude hiding (writeFile, writeFile)
+import System.Directory (removeFile)
 
+-- | This contains the information required to run the state monad for
+-- import cleaning and module spliting/mergeing.
+data Params
+    = Params
+      { scratchDir :: FilePath
+      -- ^ Location of the temporary directory for ghc output.
+      , dryRun :: Bool
+      -- ^ None of the operations that modify the modules will actually
+      -- be performed if this is ture.
+      , verbosity :: Int
+      -- ^ Increase or decrease the amount of progress reporting.
+      , hsFlags :: [String]
+      -- ^ Extra flags to pass to GHC.
+      , moduVerse :: ModuVerseState
+      -- ^ The set of modules that splitModules and catModules will
+      -- check for imports of symbols that moved.
+      , junk :: Set FilePath
+      -- ^ Paths added to this list are removed as the state monad
+      -- finishes.
+      , removeEmptyImports :: Bool
+      -- ^ If true, remove any import that became empty due to the
+      -- clean.  THe import might still be required because of the
+      -- instances it contains, but usually it is not.  Note that this
+      -- option does not affect imports that started empty and end
+      -- empty.
+      , extraImports :: Map S.ModuleName (Set S.ImportDecl)
+      -- ^ Deciding whether a module needs to be imported can be
+      -- difficult when instances are involved, this is a cheat to force
+      -- keys of the map to import the corresponding elements.
+      , testMode :: Bool
+      -- ^ For testing, do not run cleanImports on the results of the
+      -- splitModule and catModules operations.
+      } deriving (Eq, Ord, Show)
+
+-- | An instance of MonadClean.
+type CleanT m = StateT Params m
+
+instance MonadClean m => ModuVerse m where
+    getModuVerse = getParams >>= return . moduVerse
+    modifyModuVerse f = modifyParams (\ p -> p {moduVerse = f (moduVerse p)})
+
+class (MonadIO m, MonadBaseControl IO m, Functor m) => MonadClean m where
+    getParams :: m Params
+    putParams :: Params -> m ()
+
+modifyParams :: MonadClean m => (Params -> Params) -> m ()
+modifyParams f = getParams >>= putParams . f
+
+instance (MonadIO m, MonadBaseControl IO m, Functor m) => MonadClean (CleanT m) where
+    getParams = get
+    putParams = put
+
+instance MonadClean m => MonadVerbosity m where
+    getVerbosity = getParams >>= return . verbosity
+    putVerbosity v = modifyParams (\ p -> p {verbosity = v})
+
+instance MonadClean m => MonadDryRun m where
+    dry = getParams >>= return . dryRun
+    putDry x = modifyParams (\ p -> p {dryRun = x})
+
+-- | Create the environment required to do import cleaning and module
+-- splitting/merging.  This environment, StateT Params m a, is an
+-- instance of MonadClean.
+runCleanT :: (MonadIO m, MonadBaseControl IO m) => CleanT m a -> m a
+runCleanT action =
+    withTempDirectory "." "scratch" $ \ scratch ->
+    do (result, params) <- runStateT action (Params {scratchDir = scratch,
+                                                     dryRun = False,
+                                                     verbosity = 1,
+                                                     hsFlags = [],
+                                                     moduVerse = moduVerseInit,
+                                                     junk = Set.empty,
+                                                     removeEmptyImports = True,
+                                                     extraImports = Map.empty,
+                                                     testMode = False})
+       mapM_ (\ x -> liftIO (try (removeFile x)) >>= \ (_ :: Either SomeException ()) -> return ()) (toList (junk params))
+       return result
+
+markForDelete :: MonadClean m => FilePath -> m ()
+markForDelete x = modifyParams (\ p -> p {junk = insert x (junk p)})
+
 -- | If this flag is set, imports that become empty are removed.
 -- Sometimes this will lead to errors, specifically when an instance
 -- in the removed import that was required is no longer be available.
@@ -36,3 +137,16 @@
 -- split or cat.  Default is False.
 modifyTestMode :: MonadClean m => (Bool -> Bool) -> m ()
 modifyTestMode f = modifyParams (\ p -> p {testMode = f (testMode p)})
+
+-- | When we write module @m@, insert an extra line that imports the
+-- instances (only) from module @i@.
+extraImport :: MonadClean m => S.ModuleName -> S.ModuleName -> m ()
+extraImport m i =
+    modifyParams (\ p -> p {extraImports = Map.insertWith (union) m (singleton im) (extraImports p)})
+    where im = ImportDecl { importLoc = SrcLoc "<unknown>.hs" 1 1
+                          , importModule = i
+                          , importQualified = False
+                          , importSrc = False
+                          , importPkg = Nothing
+                          , importAs = Nothing
+                          , importSpecs = Just (False, []) }
diff --git a/Language/Haskell/Modules/SourceDirs.hs b/Language/Haskell/Modules/SourceDirs.hs
--- a/Language/Haskell/Modules/SourceDirs.hs
+++ b/Language/Haskell/Modules/SourceDirs.hs
@@ -1,55 +1,65 @@
-{-# LANGUAGE CPP, PackageImports, ScopedTypeVariables, StandaloneDeriving #-}
+{-# LANGUAGE CPP, FlexibleContexts, FlexibleInstances, PackageImports, ScopedTypeVariables, StandaloneDeriving, TypeSynonymInstances #-}
 {-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
 module Language.Haskell.Modules.SourceDirs
     ( SourceDirs(..)
     , modifyDirs
+    , withDirs
+    , RelPath(..)
     , PathKey(..)
+    , APath(..)
     , pathKey
+#if 0
+    , pathKey
     , pathKeyMaybe
+#endif
+    , Path(..)
     , modulePath
     , modulePathBase
     ) where
 
-import "MonadCatchIO-mtl" Control.Monad.CatchIO as IO (catch, MonadCatchIO, throw)
+import Control.Exception.Lifted as IO (catch, throw, bracket)
 import Control.Monad.Trans (liftIO, MonadIO)
+import Control.Monad.Trans.Control (MonadBaseControl)
 import Language.Haskell.Exts.Syntax as S (ModuleName(..))
 import System.Directory (canonicalizePath, doesFileExist, getCurrentDirectory)
 import System.FilePath ((<.>), (</>))
 
-class MonadCatchIO m => SourceDirs m where
+class (MonadIO m, MonadBaseControl IO m) => SourceDirs m where
     putDirs :: [FilePath] -> m ()
     getDirs :: m [FilePath]
 
 modifyDirs :: SourceDirs m => ([FilePath] -> [FilePath]) -> m ()
 modifyDirs f = getDirs >>= putDirs . f
 
+withDirs :: SourceDirs m => [FilePath] -> m a -> m a
+withDirs dirs action = bracket (getDirs >>= \ save -> putDirs dirs >> return save) putDirs (const action)
+
 -- | A FilePath that can be assumed to be unique.
 newtype PathKey = PathKey {unPathKey :: FilePath} deriving (Eq, Ord, Show)
 
-pathKey :: SourceDirs m => FilePath -> m PathKey
--- pathKey path = PathKey <$> liftIO (canonicalizePath path)
-pathKey path = findFile path >>= liftIO . canonicalizePath >>= return . PathKey
+-- | A FilePath that is relative to the SourceDir list
+newtype RelPath = RelPath {unRelPath :: FilePath} deriving (Eq, Ord, Show)
 
-pathKeyMaybe :: SourceDirs m => FilePath -> m (Maybe PathKey)
-pathKeyMaybe path = findFileMaybe path >>= maybe (return Nothing) (\ path' -> liftIO (canonicalizePath path') >>= return . Just . PathKey)
+-- | A regular filepath with a wrapper
+newtype APath = APath {unAPath :: FilePath} deriving (Eq, Ord, Show)
 
 -- | Search the path directory list, preferring an already existing file, but
 -- if there is none construct one using the first element of the directory list.
-modulePath :: SourceDirs m => String -> S.ModuleName -> m FilePath
+modulePath :: SourceDirs m => String -> S.ModuleName -> m APath
 modulePath ext name =
     findFile path `IO.catch` (\ (_ :: IOError) -> makePath)
     where
       makePath =
           do dirs <- getDirs
              case dirs of
-               [] -> return path -- should this be an error?
-               (d : _) -> return $ d </> path
+               [] -> error "Empty $PATH" -- return (APath (unRelPath path)) -- should this be an error?
+               (d : _) -> return . APath $ d </> unRelPath path
       path = modulePathBase ext name
 
 -- | Construct the base of a module path.
-modulePathBase :: String -> S.ModuleName -> FilePath
+modulePathBase :: String -> S.ModuleName -> RelPath
 modulePathBase ext (S.ModuleName name) =
-    base <.> ext
+    RelPath (base <.> ext)
     where base = case ext of
                    "hs" -> map f name
                    "lhs" -> map f name
@@ -58,22 +68,41 @@
           f '.' = '/'
           f c = c
 
--- | Search the path directory list for a source file that already exists.
--- FIXME: this should return a Maybe.
-findFile :: SourceDirs m => FilePath -> m FilePath
+class Path a where
+    findFileMaybe :: SourceDirs m => a -> m (Maybe APath)
+    pathKeyMaybe :: SourceDirs m => a -> m (Maybe PathKey)
+
+instance Path RelPath where
+    findFileMaybe (RelPath path) =
+        getDirs >>= f
+        where
+          f (dir : dirs) =
+              do let x = dir </> path
+                 exists <- liftIO $ doesFileExist x
+                 if exists then return (Just (APath x)) else f dirs
+          f [] = return Nothing
+    pathKeyMaybe path =
+        findFileMaybe path >>= maybe (return Nothing) (\ (APath path') -> liftIO (canonicalizePath path') >>= return . Just . PathKey)
+
+instance Path PathKey where
+    findFileMaybe (PathKey x) = return (Just (APath x))
+    pathKeyMaybe x = return (Just x)
+
+instance Path APath where
+    findFileMaybe (APath x) =
+        do exists <- liftIO $ doesFileExist x
+           return $ if exists then Just (APath x) else Nothing
+    pathKeyMaybe x =
+        do mpath <- findFileMaybe x
+           maybe (return Nothing) (\ (APath x) -> liftIO (canonicalizePath x) >>= return . Just . PathKey) mpath
+
+findFile :: (SourceDirs m, Path p, Show p) => p -> m APath
 findFile path =
     findFileMaybe path >>=
     maybe (do here <- liftIO getCurrentDirectory
               dirs <- getDirs
-              liftIO . throw . userError $ "findFile failed, cwd=" ++ here ++ ", dirs=" ++ show dirs ++ ", path=" ++ path)
+              liftIO . throw . userError $ "findFile failed, cwd=" ++ here ++ ", dirs=" ++ show dirs ++ ", path=" ++ show path)
           return
 
-findFileMaybe :: SourceDirs m => FilePath -> m (Maybe FilePath)
-findFileMaybe path =
-    getDirs >>= f
-    where
-      f (dir : dirs) =
-          do let x = dir </> path
-             exists <- liftIO $ doesFileExist x
-             if exists then return (Just x) else f dirs
-      f [] = return Nothing
+pathKey :: (SourceDirs m, Path p, Show p) => p -> m PathKey
+pathKey path = findFile path >>= liftIO . canonicalizePath . unAPath >>= return . PathKey
diff --git a/Language/Haskell/Modules/Split.hs b/Language/Haskell/Modules/Split.hs
--- a/Language/Haskell/Modules/Split.hs
+++ b/Language/Haskell/Modules/Split.hs
@@ -23,13 +23,14 @@
 import Language.Haskell.Exts.Pretty (defaultMode, prettyPrint, prettyPrintWithMode)
 import Language.Haskell.Exts.SrcLoc (SrcLoc(..), SrcSpanInfo(..))
 import qualified Language.Haskell.Exts.Syntax as S (ExportSpec(..), ImportDecl(..), Module(..), ModuleName(..), Name(..))
+import Language.Haskell.Modules.Common (doResult, ModuleResult(..), reportResult)
 import Language.Haskell.Modules.Fold (echo, echo2, foldDecls, foldExports, foldHeader, foldImports, foldModule, ignore, ignore2)
 import Language.Haskell.Modules.Imports (cleanResults)
-import Language.Haskell.Modules.Internal (doResult, ModuleResult(..), MonadClean(getParams), Params(extraImports))
-import Language.Haskell.Modules.ModuVerse (getNames, ModuleInfo(..), moduleName, parseModule, findModule)
-import Language.Haskell.Modules.SourceDirs (modulePathBase, pathKey)
+import Language.Haskell.Modules.ModuVerse (findModule, getNames, ModuleInfo(..), moduleName, parseModule)
+import Language.Haskell.Modules.Params (MonadClean(getParams), Params(extraImports))
+import Language.Haskell.Modules.SourceDirs (modulePathBase, APath(..), pathKey)
 import Language.Haskell.Modules.Util.QIO (qLnPutStr, quietly)
-import Language.Haskell.Modules.Util.Symbols (exports, imports, symbols)
+import Language.Haskell.Modules.Util.Symbols (exports, imports, symbols, members)
 import Prelude hiding (writeFile)
 import System.FilePath ((<.>))
 
@@ -65,13 +66,13 @@
             -> FilePath
             -> m [ModuleResult]
 splitModule symToModule path =
-    do info <- pathKey path >>= parseModule
+    do info <- pathKey (APath path) >>= parseModule
        splitModuleBy symToModule info
 
 -- | Do splitModuleBy with the default symbol to module mapping (was splitModule)
 splitModuleDecls :: MonadClean m => FilePath -> m [ModuleResult]
 splitModuleDecls path =
-    do info <- pathKey path >>= parseModule
+    do info <- pathKey (APath path) >>= parseModule
        splitModuleBy (defaultSymbolToModule info) info
 
 splitModuleBy :: MonadClean m => (Maybe S.Name -> S.ModuleName) -> ModuleInfo -> m [ModuleResult]
@@ -81,7 +82,7 @@
 splitModuleBy _ m@(ModuleInfo (A.Module _ _ _ _ [_]) _ _ key) = return [Unchanged (moduleName m) key] -- One declaration - nothing to split (but maybe we should anyway?)
 splitModuleBy _ (ModuleInfo (A.Module _ Nothing _ _ _) _ _ _) = throw $ userError $ "splitModule: no explicit header"
 splitModuleBy symToModule inInfo =
-    do qLnPutStr ("Splitting " ++ prettyPrint (moduleName inInfo))
+    do qLnPutStr ("Splitting module " ++ prettyPrint (moduleName inInfo))
        quietly $
          do eiMap <- getParams >>= return . extraImports
             -- The name of the module to be split
@@ -90,10 +91,10 @@
             changes <- List.mapM (doModule symToModule eiMap inInfo inName outNames) (toList allNames)
             -- No good reason to use sets here
             -- changes <- doSplit symToModule info >>= return . collisionCheck univ
-            List.mapM_ doResult changes           -- Write the new modules
-            List.mapM_ reportResult changes
+            changes' <- List.mapM doResult changes           -- Write the new modules
+            List.mapM_ (\ x -> qLnPutStr ("splitModule: " ++ reportResult x)) changes'
             -- Clean the new modules after all edits are finished
-            cleanResults changes
+            cleanResults changes'
     where
 
 {-    collisionCheck univ s =
@@ -101,11 +102,6 @@
           then error ("One or more module to be created by splitModule already exists: " ++ show (Set.toList illegal))
           else s -}
 
-      reportResult x@(Modified (S.ModuleName _) key _) = qLnPutStr ("splitModule: modifying " ++ show key) >> return x
-      reportResult x@(Created (S.ModuleName name) _) = qLnPutStr ("splitModule: creating " ++ name) >> return x
-      reportResult x@(Removed (S.ModuleName _) key) = qLnPutStr ("splitModule: removing " ++ show key) >> return x
-      reportResult x = return x
-
       outNames = Set.map symToModule (union (declared inInfo) (exported inInfo))
 
 doModule :: MonadClean m =>
@@ -113,21 +109,21 @@
          -> Map S.ModuleName (Set S.ImportDecl)
          -> ModuleInfo -> S.ModuleName
          -> Set S.ModuleName -> S.ModuleName -> m ModuleResult
-doModule symToModule eiMap inInfo inName outNames thisName@(S.ModuleName s) =
+doModule symToModule eiMap inInfo inName outNames thisName =
     case () of
       _ | member thisName outNames ->
-            findModule s >>= \ thisInfo ->
+            findModule thisName >>= \ thisInfo ->
             return $ if thisName == inName
-                     then Modified thisName (key_ inInfo) newModule
+                     then ToBeModified thisName (key_ inInfo) newModule
                      else case thisInfo of
                             Just (ModuleInfo {key_ = key}) ->
                                 error $ "splitModule: output module already exists: " ++ show key
-                            _ -> Created thisName newModule
-        | thisName == inName -> return (Removed thisName (key_ inInfo))
+                            _ -> ToBeCreated thisName newModule
+        | thisName == inName -> return (ToBeRemoved thisName (key_ inInfo))
         | True ->
             pathKey (modulePathBase "hs" thisName) >>= parseModule >>= \ oldInfo@(ModuleInfo _ oldText _ _) ->
             let newText = updateImports oldInfo in
-            return $ if newText /= oldText then Modified thisName (key_ oldInfo) newText else Unchanged thisName (key_ oldInfo)
+            return $ if newText /= oldText then ToBeModified thisName (key_ oldInfo) newText else Unchanged thisName (key_ oldInfo)
     where
       -- Build a new module given its name and the list of
       -- declarations it should contain.
@@ -186,7 +182,8 @@
                 Map.filter imported moduleDeclMap
                 where
                   imported pairs =
-                      let declared' = justs (Set.unions (List.map (symbols . fst) pairs)) in
+                      let declared' = justs (Set.unions (List.map (symbols . fst) pairs ++
+                                                         List.map (members . fst) pairs)) in
                       not (Set.null (Set.intersection declared' referenced))
 
       newDecls = concatMap snd modDecls
diff --git a/Language/Haskell/Modules/Util/Symbols.hs b/Language/Haskell/Modules/Util/Symbols.hs
--- a/Language/Haskell/Modules/Util/Symbols.hs
+++ b/Language/Haskell/Modules/Util/Symbols.hs
@@ -4,21 +4,17 @@
     ( FoldDeclared(foldDeclared)
     , FoldMembers(foldMembers)
     , symbols
+    , members
     , exports
     , imports
-    , tests
     ) where
 
 import Data.List (sort)
 import Data.Maybe (mapMaybe)
 import Data.Set as Set (empty, insert, Set, toList)
 import Language.Haskell.Exts.Annotated.Simplify (sName)
-import qualified Language.Haskell.Exts.Annotated.Syntax as A (ClassDecl(..), ConDecl(..), Decl(..), DeclHead(..), Exp(..), ExportSpec(..), FieldDecl(..), GadtDecl(..), ImportSpec(..), InstHead(..), Match(..), Name(..), Pat(..), PatField(..), QName(..), QualConDecl(..), Rhs(..), RPat(..), Type(..))
-import Language.Haskell.Exts.Pretty (prettyPrint)
-import Language.Haskell.Exts.SrcLoc (SrcSpan(..), SrcSpanInfo(..))
+import qualified Language.Haskell.Exts.Annotated.Syntax as A (ClassDecl(..), ConDecl(..), Decl(..), DeclHead(..), ExportSpec(..), FieldDecl(..), GadtDecl(..), ImportSpec(..), InstHead(..), Match(..), Name, Pat(..), PatField(..), QName(..), QualConDecl(..), RPat(..))
 import qualified Language.Haskell.Exts.Syntax as S (CName(..), ExportSpec(..), ImportSpec(..), Name(..), QName(..))
-import Language.Haskell.Modules.Util.SrcLoc ()
-import Test.HUnit (assertEqual, Test(TestCase, TestList))
 
 -- | Do a fold over the names that are declared in a declaration (not
 -- every name that appears, just the ones that the declaration is
@@ -152,7 +148,7 @@
               ([], []) -> []
               ([], _) -> error "exports: members with no top level name"
               (ns, []) -> map (S.EVar . S.UnQual) ns
-              (_ns, _ms) -> error "exports: multiple top level names and member names"
+              y -> error $ "exports: multiple top level names and member names: " ++ show y
 
 imports :: (FoldDeclared a, FoldMembers a) => a -> [S.ImportSpec]
 imports x = case (justs (symbols x), justs (members x)) of
@@ -161,9 +157,10 @@
               ([], []) -> []
               ([], _ms) -> error "exports: members with no top level name"
               (ns, []) -> map S.IVar ns
-              (_ns, _ms) -> error "exports: multiple top level names and member names"
+              y -> error $ "imports: multiple top level names and member names: " ++ show y
 
--- | Fold over the declared members - e.g. the method names of a class declaration, the constructors of a data declaration.
+-- | Fold over the declared members - e.g. the method names of a class
+-- declaration, the constructors of a data declaration.
 class FoldMembers a where
     foldMembers :: forall r. (Maybe S.Name -> r -> r) -> r -> a -> r
 
@@ -188,18 +185,3 @@
 
 instance FoldDeclared (A.GadtDecl l) where
     foldDeclared f r (A.GadtDecl _ x _) = foldDeclared f r x
-
-tests :: Test
-tests = TestList [test1, test2, test3, test4]
-
-test1 :: Test
-test1 = TestCase (assertEqual "DefaultDecl" " \ndefault (foo)" (prettyPrint (A.DefaultDecl def [A.TyVar def (A.Ident def "foo")] :: A.Decl SrcSpanInfo)))
-test2 :: Test
-test2 = TestCase (assertEqual "PatBind" "pvar :: typ = unqualrhs" (prettyPrint (A.PatBind def (A.PVar def (A.Ident def "pvar")) (Just (A.TyVar def (A.Ident def "typ"))) (A.UnGuardedRhs def (A.Var def (A.UnQual def (A.Ident def "unqualrhs")))) Nothing :: A.Decl SrcSpanInfo)))
-test3 :: Test
-test3 = TestCase (assertEqual "Pat" "pvar" (prettyPrint (A.PVar def (A.Ident def "pvar") :: A.Pat SrcSpanInfo)))
-test4 :: Test
-test4 = TestCase (assertEqual "Pat" "unqual pvar" (prettyPrint (A.PApp def (A.UnQual def (A.Ident def "unqual")) [A.PVar def (A.Ident def "pvar")] :: A.Pat SrcSpanInfo)))
-
-def :: SrcSpanInfo
-def = SrcSpanInfo (SrcSpan "test" 1 1 1 1) []
diff --git a/Language/Haskell/Modules/Util/Temp.hs b/Language/Haskell/Modules/Util/Temp.hs
--- a/Language/Haskell/Modules/Util/Temp.hs
+++ b/Language/Haskell/Modules/Util/Temp.hs
@@ -1,16 +1,17 @@
-{-# LANGUAGE PackageImports #-}
+{-# LANGUAGE FlexibleContexts, PackageImports #-}
 module Language.Haskell.Modules.Util.Temp
     ( withTempDirectory
     ) where
 
 import qualified Control.Exception as IO (catch)
-import "MonadCatchIO-mtl" Control.Monad.CatchIO as IOT (bracket, MonadCatchIO)
+import Control.Exception.Lifted as IOT (bracket)
 import Control.Monad.Trans (liftIO, MonadIO)
+import Control.Monad.Trans.Control (MonadBaseControl)
 import System.Directory (removeDirectoryRecursive)
 import qualified System.IO.Temp as Temp (createTempDirectory)
 
--- | Adapted from 'System.IO.Temp.withTempDirectory' to work in MonadCatchIO instances.
-withTempDirectory :: MonadCatchIO m =>
+-- | Adapted from 'System.IO.Temp.withTempDirectory' to work in MonadIO instances.
+withTempDirectory :: (MonadIO m, MonadBaseControl IO m) =>
                      FilePath -- ^ Temp directory to create the directory in
                   -> String   -- ^ Directory name template. See 'openTempFile'.
                   -> (FilePath -> m a) -- ^ Callback that can use the directory
diff --git a/Language/Haskell/Modules/Util/Test.hs b/Language/Haskell/Modules/Util/Test.hs
--- a/Language/Haskell/Modules/Util/Test.hs
+++ b/Language/Haskell/Modules/Util/Test.hs
@@ -10,6 +10,7 @@
 
 import Control.Monad (foldM)
 import Data.List as List (filter, isPrefixOf, isSuffixOf, map)
+import Language.Haskell.Exts.Syntax (ModuleName(..))
 import System.Directory (doesDirectoryExist, doesFileExist, getDirectoryContents)
 import System.Exit (ExitCode)
 import System.FilePath ((</>))
@@ -135,9 +136,9 @@
 -- MonadClean and use the value of sourceDirs to remove prefixes from
 -- the module paths.  And then it should look at the module text to
 -- see what the module name really is.
-findHsModules :: [FilePath] -> IO [String]
+findHsModules :: [FilePath] -> IO [ModuleName]
 findHsModules tops =
     findHsFiles tops >>= return . List.map asModuleName
     where
       asModuleName path =
-          List.map (\ c -> if c == '/' then '.' else c) (take (length path - 3) path)
+          ModuleName (List.map (\ c -> if c == '/' then '.' else c) (take (length path - 3) path))
diff --git a/Tests.hs b/Tests.hs
--- a/Tests.hs
+++ b/Tests.hs
@@ -11,22 +11,20 @@
 import Language.Haskell.Exts.Syntax (ModuleName(ModuleName))
 import Language.Haskell.Modules (CleanT, mergeModules, modifyExtensions, MonadClean, noisily, putModule, runCleanT, splitModuleDecls, withCurrentDirectory)
 import Language.Haskell.Modules.Util.Test (diff', logicModules, rsync)
-import System.Environment (getArgs)
 import System.Exit (ExitCode(ExitSuccess, ExitFailure), exitWith)
 import System.Process (system)
 import Test.HUnit (assertEqual, Counts(..), runTestTT, Test(TestList, TestCase, TestLabel))
 import qualified Tests.Fold as Fold (tests)
 import qualified Tests.Imports as Imports (tests)
 import qualified Tests.Merge as Merge (tests)
-import qualified Tests.Split as Split (slow, tests)
+import qualified Tests.Split as Split (tests, slow)
 import qualified Tests.SrcLoc as SrcLoc (tests)
+import qualified Tests.Symbols as Symbols (tests)
 
 main :: IO ()
 main =
-    do args <- getArgs
-       _ <- system "[ -d testdata ] || tar xfz testdata.tar.gz"
-       counts <- runTestTT (TestList $ [TestLabel "Main" Main.tests] ++
-                                       if elem "--slow" args then [TestLabel "Slow" Main.slow] else [])
+    do _ <- system "[ -d testdata ] || tar xfz testdata.tar.gz"
+       counts <- runTestTT Main.tests
        putStrLn (show counts)
        case (errors counts + failures counts) of
          0 -> exitWith ExitSuccess
@@ -45,18 +43,19 @@
 
 tests :: Test
 tests = TestList [ Main.test1
+                 , TestLabel "Symbols" Symbols.tests
                  , TestLabel "SrcLoc" SrcLoc.tests
                  , TestLabel "Fold" Fold.tests
                  , TestLabel "Imports" Imports.tests
-                 -- If split-merge-merge fails try split and split-merge.
                  , TestLabel "Split" Split.tests
                  , TestLabel "Merge" Merge.tests
                  ]
 
 slow :: Test
-slow = TestList [ Main.logictest "split-merge-merge" test2c
-                , Main.logictest "split-merge" test2b
-                , Main.logictest "split" test2a
+slow = TestList [ -- No need to do test2b or test2a if test2c passes.
+                  Main.logictest "split-merge-merge" test2c
+                  -- , Main.logictest "split-merge" test2b
+                  -- , Main.logictest "split" test2a
                 , Split.slow
                 ]
 
@@ -72,16 +71,16 @@
       test parsed comments text = return (exactPrint parsed comments, text)
 
 -- logictest :: String -> ([String] -> CleanT m ()) -> Test
-logictest :: String -> ([String] -> CleanT IO ()) -> Test
+logictest :: String -> ([ModuleName] -> CleanT IO ()) -> Test
 logictest s f =
     TestLabel s $ TestCase $
     do _ <- rsync "testdata/logic" "tmp"
-       _ <- withCurrentDirectory "tmp" $ runCleanT $ noisily $ f logicModules
+       _ <- withCurrentDirectory "tmp" $ runCleanT $ noisily $ f (map ModuleName logicModules)
        (code, out, err) <- diff' ("testdata/" ++ s ++ "-expected") "tmp"
        let out' = unlines (filter (not . isPrefixOf "Binary files") . map (takeWhile (/= '\t')) $ (lines out))
        assertEqual s (ExitSuccess, "", "") (code, out', err)
 
-test2a :: MonadClean m => [String] -> m ()
+test2a :: MonadClean m => [ModuleName] -> m ()
 test2a u =
          do modifyExtensions (++ [MultiParamTypeClasses])
             -- We *must* clean the split results, or there will be
@@ -90,7 +89,7 @@
             _ <- splitModuleDecls "Data/Logic/Classes/Literal.hs"
             return ()
 
-test2b :: MonadClean m => [String] -> m ()
+test2b :: MonadClean m => [ModuleName] -> m ()
 test2b u =
          do modifyExtensions (++ [MultiParamTypeClasses])
             mapM_ putModule u
@@ -102,7 +101,7 @@
                    (ModuleName "Data.Logic.Classes.FirstOrder")
             return ()
 
-test2c :: MonadClean m => [String] -> m ()
+test2c :: MonadClean m => [ModuleName] -> m ()
 test2c u =
          do modifyExtensions (++ [MultiParamTypeClasses])
             mapM_ putModule u
diff --git a/Tests/Fold.hs b/Tests/Fold.hs
--- a/Tests/Fold.hs
+++ b/Tests/Fold.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE FlexibleInstances, StandaloneDeriving #-}
 module Tests.Fold where
 
 import Data.Foldable (fold)
@@ -5,22 +6,28 @@
 import Data.Sequence as Seq (filter, fromList, Seq, zip, (|>))
 import Data.Set.Extra as Set (fromList)
 import Data.Tree (Tree(..))
+import qualified Language.Haskell.Exts.Annotated as A
+import Language.Haskell.Exts.Annotated.Syntax ({- Eq Module -})
+import qualified Language.Haskell.Exts.Parser as Exts
 import Language.Haskell.Exts.SrcLoc (SrcLoc(..), SrcSpan(..), SrcSpanInfo(..))
 import Language.Haskell.Modules.Common (withCurrentDirectory)
 import Language.Haskell.Modules.Fold (echo, echo2, foldDecls, foldModule)
-import Language.Haskell.Modules.Internal (runCleanT)
 import Language.Haskell.Modules.ModuVerse (ModuleInfo(..), parseModule)
-import Language.Haskell.Modules.SourceDirs (pathKey)
+import Language.Haskell.Modules.Params (runCleanT)
+import Language.Haskell.Modules.SourceDirs (pathKey, APath(..))
 import Language.Haskell.Modules.Util.SrcLoc (HasSpanInfo(..), makeTree)
 import Test.HUnit (assertEqual, Test(TestList, TestCase, TestLabel))
 
+deriving instance Eq (Exts.ParseResult (A.Module SrcSpanInfo, [A.Comment]))
+deriving instance Show (Exts.ParseMode)
+
 tests :: Test
-tests = TestLabel "Clean" (TestList [test1, test1b, test3, test4, test5, test5b, test6, test7])
+tests = TestLabel "Clean" (TestList [test1, test1b, test3, fold3b, fold3c, test4, test5, test5b, test6, test7])
 
 test1 :: Test
 test1 =
     TestLabel "test1" $ TestCase $ withCurrentDirectory "testdata/debian" $
-    do let path = "Debian/Repo/Orphans.hs"
+    do let path = APath "Debian/Repo/Orphans.hs"
        mi <- runCleanT $ pathKey path >>= parseModule
        let (output, original) = test mi
        assertEqual "echo" original output
@@ -31,7 +38,7 @@
 test1b :: Test
 test1b =
     TestLabel "test1b" $ TestCase $ withCurrentDirectory "testdata/debian" $
-    do let path = "Debian/Repo/Sync.hs"
+    do let path = APath "Debian/Repo/Sync.hs"
        mi <- runCleanT $ pathKey path >>= parseModule
        let output = test mi
        assertEqual "echo" mempty (Seq.filter (\ (a, b) -> a /= b) (Seq.zip expected output))
@@ -74,7 +81,7 @@
 test3 :: Test
 test3 =
     TestLabel "test3" $ TestCase $ withCurrentDirectory "testdata" $
-    do let path = "Equal.hs"
+    do let path = APath "Equal.hs"
        mi <- runCleanT $ pathKey path >>= parseModule
        let (output, original) = test mi
        assertEqual "echo" original output
@@ -82,10 +89,32 @@
       test :: ModuleInfo -> (String, String)
       test m@(ModuleInfo _ text _ _) = (fold (foldModule echo2 echo echo echo echo2 echo echo2 echo echo echo2 m mempty), text)
 
+fold3b :: Test
+fold3b =
+    TestLabel "fold3b" $ TestCase $ withCurrentDirectory "testdata" $
+    do let path = APath "fold3b/Main.hs"
+       mi <- runCleanT $ pathKey path >>= parseModule
+       let (output, original) = test mi
+       assertEqual "echo" original output
+    where
+      test :: ModuleInfo -> (String, String)
+      test m@(ModuleInfo _ text _ _) = (fold (foldModule echo2 echo echo echo echo2 echo echo2 echo echo echo2 m mempty), text)
+
+fold3c :: Test
+fold3c =
+    TestLabel "fold3c" $ TestCase $
+    do let path = APath "testdata/fold9.hs"
+       mi <- runCleanT $ pathKey path >>= parseModule
+       let (output, original) = test mi
+       assertEqual "echo" original output
+    where
+      test :: ModuleInfo -> (String, String)
+      test m@(ModuleInfo _ text _ _) = (fold (foldModule echo2 echo echo echo echo2 echo echo2 echo echo echo2 m mempty), text)
+
 test5 :: Test
 test5 =
     TestLabel "fold5" $ TestCase $
-    do let path = "testdata/fold5.hs" -- "testdata/logic/Data/Logic/Classes/Literal.hs"
+    do let path = APath "testdata/fold5.hs" -- "testdata/logic/Data/Logic/Classes/Literal.hs"
        mi <- runCleanT $ pathKey path >>= parseModule
        -- let actual = map f (adjustSpans text comments (spans m))
        -- assertEqual "spans" original actual
@@ -99,7 +128,7 @@
 test5b :: Test
 test5b =
     TestLabel "test5b" $ TestCase $
-    do let path = "testdata/logic/Data/Logic/Classes/Literal.hs"
+    do let path = APath "testdata/logic/Data/Logic/Classes/Literal.hs"
        mi <- runCleanT $ pathKey path >>= parseModule
        let actual = foldDecls (\ _ a b c r -> r ++ [(a, b, c)]) (\ s r -> r ++ [("", s, "")]) mi []
        assertEqual "spans" expected actual
@@ -159,7 +188,7 @@
 test7 :: Test
 test7 =
     TestCase $
-    do mi <- runCleanT $ pathKey "testdata/Fold7.hs" >>= parseModule
+    do mi <- runCleanT $ pathKey (APath "testdata/Fold7.hs") >>= parseModule
        let actual = foldModule (\ s r -> r |> (s, "", ""))
                                (\ _ b s a r -> r |> (b, s, a))
                                (\ _ b s a r -> r |> (b, s, a))
diff --git a/Tests/Imports.hs b/Tests/Imports.hs
--- a/Tests/Imports.hs
+++ b/Tests/Imports.hs
@@ -4,6 +4,7 @@
 import Language.Haskell.Exts.Extension (Extension(FlexibleInstances, StandaloneDeriving, TypeSynonymInstances))
 import qualified Language.Haskell.Exts.Syntax as S (ModuleName(ModuleName))
 import Language.Haskell.Modules (cleanImports, modifyExtensions, modifyTestMode, modulePathBase, putDirs, runCleanT, withCurrentDirectory)
+import Language.Haskell.Modules.SourceDirs (RelPath(unRelPath))
 import Language.Haskell.Modules.Util.Test (diff, rsync)
 import System.Exit (ExitCode(..))
 import System.FilePath ((</>))
@@ -19,8 +20,8 @@
       (do rsync "testdata/debian" "tmp"
           let name = S.ModuleName "Debian.Repo.Types.PackageIndex"
           let base = modulePathBase "hs" name
-          _ <- withCurrentDirectory "tmp" (runCleanT (cleanImports [base]))
-          (code, out, err) <- readProcessWithExitCode "diff" ["-ru", "testdata/debian" </> base, "tmp" </> base] ""
+          _ <- withCurrentDirectory "tmp" $ (runCleanT (cleanImports [unRelPath base]))
+          (code, out, err) <- readProcessWithExitCode "diff" ["-ru", "testdata/debian" </> unRelPath base, "tmp" </> unRelPath base] ""
           assertEqual "cleanImports"
                          (ExitFailure 1,
                           ["@@ -22,13 +22,13 @@",
@@ -48,8 +49,8 @@
       (do rsync "testdata/debian" "tmp"
           let name = S.ModuleName "Debian.Repo.PackageIndex"
               base = modulePathBase "hs" name
-          _ <- withCurrentDirectory "tmp" (runCleanT (cleanImports [base]))
-          (code, out, err) <- readProcessWithExitCode "diff" ["-ru", "testdata/debian" </> base, "tmp" </> base] ""
+          _ <- withCurrentDirectory "tmp" (runCleanT (cleanImports [unRelPath base]))
+          (code, out, err) <- readProcessWithExitCode "diff" ["-ru", "testdata/debian" </> unRelPath base, "tmp" </> unRelPath base] ""
           assertEqual "cleanImports" (ExitSuccess, "", "") (code, out, err))
 
 -- | Can we handle a Main module in a file named something other than Main.hs?
@@ -57,7 +58,7 @@
 test3 =
     TestLabel "imports3" $ TestCase
       (rsync "testdata/imports3" "tmp" >>
-       runCleanT (putDirs ["tmp"] >> cleanImports ["NotMain.hs"]) >>
+       runCleanT (putDirs ["tmp"] >> cleanImports ["tmp/NotMain.hs"]) >>
        assertEqual "module name" () ())
 
 -- | Preserve imports with a "hiding" clause
@@ -65,7 +66,7 @@
 test4 =
     TestLabel "imports4" $ TestCase
       (rsync "testdata/imports4" "tmp" >>
-       runCleanT (putDirs ["tmp"] >> cleanImports ["Hiding.hs"]) >>
+       runCleanT (putDirs ["tmp"] >> cleanImports ["tmp/Hiding.hs"]) >>
        -- Need to check the text of Hiding.hs, but at least this verifies that there was no crash
        assertEqual "module name" () ())
 
@@ -77,7 +78,7 @@
           _ <- runCleanT
                  (putDirs ["tmp"] >>
                   modifyExtensions (++ [StandaloneDeriving, TypeSynonymInstances, FlexibleInstances]) >>
-                  cleanImports ["Deriving.hs"])
+                  cleanImports ["tmp/Deriving.hs"])
           (code, out, err) <- diff "testdata/imports5" "tmp"
           assertEqual "standalone deriving"
                       (ExitFailure 1,
diff --git a/Tests/Merge.hs b/Tests/Merge.hs
--- a/Tests/Merge.hs
+++ b/Tests/Merge.hs
@@ -17,7 +17,7 @@
          _result <- runCleanT $ noisily $ noisily $ noisily $
            do putDirs ["tmp"]
               modifyTestMode (const True)
-              mapM_ putModule repoModules
+              mapM_ (putModule . S.ModuleName) repoModules
               mergeModules
                      [S.ModuleName "Debian.Repo.AptCache", S.ModuleName "Debian.Repo.AptImage"]
                      (S.ModuleName "Debian.Repo.Cache")
@@ -31,7 +31,7 @@
          _result <- runCleanT $
            do putDirs ["tmp"]
               modifyTestMode (const True)
-              mapM_ putModule repoModules
+              mapM_ (putModule . S.ModuleName) repoModules
               mergeModules
                      [S.ModuleName "Debian.Repo.Types.Slice", S.ModuleName "Debian.Repo.Types.Repo", S.ModuleName "Debian.Repo.Types.EnvPath"]
                      (S.ModuleName "Debian.Repo.Types.Common")
@@ -45,7 +45,7 @@
          _result <- withCurrentDirectory "tmp" $
                    runCleanT $
            do modifyTestMode (const True)
-              mapM_ putModule repoModules
+              mapM_ (putModule . S.ModuleName) repoModules
               mergeModules
                      [S.ModuleName "Debian.Repo.Types.Slice",
                       S.ModuleName "Debian.Repo.Types.Repo",
@@ -59,7 +59,7 @@
     TestCase $
       do _ <- rsync "testdata/merge4" "tmp"
          _ <- withCurrentDirectory "tmp" $ runCleanT $
-              do mapM_ putModule ["In1", "In2", "M1"]
+              do mapM_ (putModule . S.ModuleName) ["In1", "In2", "M1"]
                  mergeModules [S.ModuleName "In1", S.ModuleName "In2"] (S.ModuleName "Out")
          (code, out, err) <- diff "testdata/merge4-expected" "tmp"
          assertEqual "mergeModules4" (ExitSuccess, "", "") (code, out, err)
@@ -70,7 +70,7 @@
       do _ <- rsync "testdata/merge5" "tmp"
          _ <- withCurrentDirectory "tmp" $ runCleanT $ noisily $ noisily $ noisily $
               do modifyTestMode (const True)
-                 List.mapM_ putModule
+                 List.mapM_ (putModule . S.ModuleName)
                             ["Apt.AptIO", "Apt.AptIOT", "Apt.AptState",
                              "Apt.InitState", "Apt.Instances", "Apt.MonadApt"]
                  mergeModules [S.ModuleName "Apt.AptIO", S.ModuleName "Apt.AptIOT", S.ModuleName "Apt.AptState",
diff --git a/Tests/Split.hs b/Tests/Split.hs
--- a/Tests/Split.hs
+++ b/Tests/Split.hs
@@ -2,7 +2,7 @@
 
 import Control.Monad as List (mapM_)
 import qualified Language.Haskell.Exts.Syntax as S (ModuleName(..), Name(Ident))
-import Language.Haskell.Modules (modifyTestMode, noisily, putDirs, putModule, runCleanT, splitModule, splitModuleDecls, withCurrentDirectory, findHsModules)
+import Language.Haskell.Modules (modifyTestMode, noisily, putDirs, putModule, runCleanT, splitModule, splitModuleDecls, withCurrentDirectory, findHsModules, extraImport)
 import Language.Haskell.Modules.Util.Test (diff, repoModules, rsync)
 import Prelude hiding (writeFile)
 import System.Exit (ExitCode(ExitSuccess, ExitFailure))
@@ -20,10 +20,10 @@
       do _ <- rsync "testdata/debian" "tmp"
          _ <- runCleanT $ noisily $ noisily $
            do putDirs ["tmp"]
-              mapM_ putModule repoModules
-              splitModuleDecls "Debian/Repo/Package.hs"
+              mapM_ putModule (map S.ModuleName repoModules)
+              splitModuleDecls "tmp/Debian/Repo/Package.hs"
          (code, out, err) <- diff "testdata/split1-expected" "tmp"
-         assertEqual "splitModule" (ExitSuccess, "", "") (code, out, err)
+         assertEqual "split1" (ExitSuccess, "", "") (code, out, err)
 
 split2a :: Test
 split2a =
@@ -32,10 +32,10 @@
        _ <- runCleanT $ noisily $ noisily $
          do modifyTestMode (const True)
             putDirs ["tmp"]
-            putModule "Split"
-            splitModuleDecls "Split.hs"
+            putModule (S.ModuleName "Split")
+            splitModuleDecls "tmp/Split.hs"
        (code, out, err) <- diff "testdata/split2-expected" "tmp"
-       assertEqual "split2" (ExitSuccess, "", "") (code, out, err)
+       assertEqual "split2a" (ExitSuccess, "", "") (code, out, err)
 
 split2b :: Test
 split2b =
@@ -43,23 +43,26 @@
     do _ <- rsync "testdata/split2" "tmp"
        _ <- runCleanT $ noisily $ noisily $
          do putDirs ["tmp"]
-            putModule "Split"
-            splitModuleDecls "Split.hs"
+            putModule (S.ModuleName "Split")
+            splitModuleDecls "tmp/Split.hs"
        (code, out, err) <- diff "testdata/split2-clean-expected" "tmp"
        -- The output of splitModule is "correct", but it will not be
        -- accepted by GHC until the fix for
        -- http://hackage.haskell.org/trac/ghc/ticket/8011 is
        -- available.
-       assertEqual "split2-clean" (ExitFailure 1,"diff -ru '--exclude=*~' '--exclude=*.imports' testdata/split2-clean-expected/Split/Clean.hs tmp/Split/Clean.hs\n--- testdata/split2-clean-expected/Split/Clean.hs\n+++ tmp/Split/Clean.hs\n@@ -6,7 +6,7 @@\n     ) where\n \n import Data.Char (isAlphaNum)\n-import URL (ToURL(toURL), URLT)\n+import URL (ToURL(URLT, toURL))\n \n clean :: (ToURL url, Show (URLT url)) => url -> String\n clean = filter isAlphaNum . show . toURL\n", "") (code, out, err)
+       assertEqual "split2b" (ExitFailure 1,"diff -ru '--exclude=*~' '--exclude=*.imports' testdata/split2-clean-expected/Split/Clean.hs tmp/Split/Clean.hs\n--- testdata/split2-clean-expected/Split/Clean.hs\n+++ tmp/Split/Clean.hs\n@@ -6,7 +6,7 @@\n     ) where\n \n import Data.Char (isAlphaNum)\n-import URL (ToURL(toURL), URLT)\n+import URL (ToURL(URLT, toURL))\n \n clean :: (ToURL url, Show (URLT url)) => url -> String\n clean = filter isAlphaNum . show . toURL\n", "") (code, out, err)
 
 split4 :: Test
 split4 =
     TestLabel "Split4" $ TestCase $
     do _ <- rsync "testdata/split4" "tmp"
        _ <- withCurrentDirectory "tmp" $
-         runCleanT $ noisily $ noisily $ modifyTestMode (const True) >> putModule "Split4" >> splitModuleDecls "Split4.hs"
+         runCleanT $ noisily $ noisily $
+           modifyTestMode (const True) >>
+           putModule (S.ModuleName "Split4") >>
+           splitModuleDecls "Split4.hs"
        result <- diff "testdata/split4-expected" "tmp"
-       assertEqual "Split4" (ExitSuccess, "", "") result
+       assertEqual "split4" (ExitSuccess, "", "") result
 
 split4b :: Test
 split4b =
@@ -68,10 +71,10 @@
        _ <- withCurrentDirectory "tmp" $
          runCleanT $ noisily $ noisily $
            modifyTestMode (const True) >>
-           putModule "Split4" >>
+           putModule (S.ModuleName "Split4") >>
            splitModule f "Split4.hs"
        result <- diff "testdata/split4b-expected" "tmp"
-       assertEqual "Split4" (ExitSuccess, "", "") result
+       assertEqual "split4b" (ExitSuccess, "", "") result
     where
       f :: Maybe S.Name -> S.ModuleName
       f (Just (S.Ident "getPackages")) = S.ModuleName ("Split4.A")
@@ -85,10 +88,10 @@
        _ <- withCurrentDirectory "tmp" $
          runCleanT $ noisily $ noisily $
            modifyTestMode (const True) >>
-           putModule "Split4" >>
+           putModule (S.ModuleName "Split4") >>
            splitModule f "Split4.hs"
        result <- diff "testdata/split4c-expected" "tmp"
-       assertEqual "Split4" (ExitSuccess, "", "") result
+       assertEqual "split4c" (ExitSuccess, "", "") result
     where
       f :: Maybe S.Name -> S.ModuleName
       f (Just (S.Ident "getPackages")) = S.ModuleName ("Split4.A")
@@ -101,11 +104,11 @@
     do _ <- rsync "testdata/split5" "tmp"
        _ <- withCurrentDirectory "tmp" $
          runCleanT $ noisily $ noisily $
-           List.mapM_ putModule ["A", "B", "C", "D", "E"] >>
+           List.mapM_ (putModule . S.ModuleName) ["A", "B", "C", "D", "E"] >>
            modifyTestMode (const True) >>
            splitModuleDecls "B.hs"
        result <- diff "testdata/split5-expected" "tmp"
-       assertEqual "Split5" (ExitSuccess, "", "") result
+       assertEqual "split5" (ExitSuccess, "", "") result
 
 split6 :: Test
 split6 =
@@ -117,7 +120,62 @@
            mapM putModule modules >>
            splitModule f "Debian/Repo/Monads/Apt.hs"
        result <- diff "testdata/split6-expected" "tmp"
-       assertEqual "Split6" (ExitSuccess, "", "") result
+       assertEqual "split6" (ExitSuccess, "", "") result
     where
       f (Just (S.Ident "countTasks")) = S.ModuleName "IO"
       f _ = S.ModuleName "Debian.Repo.Monads.Apt"
+
+-- This code is, in some sense, inherently unsplittable.
+split7 :: Test
+split7 =
+    TestLabel "split7" $ TestCase $
+    do _ <- rsync "testdata/fold3b" "tmp"
+       _ <- withCurrentDirectory "tmp" $ runCleanT $
+            do putModule (S.ModuleName "Main")
+               extraImport (S.ModuleName "Main.GetPasteById") (S.ModuleName "Main.Instances")
+               extraImport (S.ModuleName "Main.GetRecentPastes") (S.ModuleName "Main.Instances")
+               extraImport (S.ModuleName "Main.InitialCtrlVState") (S.ModuleName "Main.Instances")
+               extraImport (S.ModuleName "Main.InsertPaste") (S.ModuleName "Main.Instances")
+               splitModule f "Main.hs"
+       result <- diff "testdata/split7-expected" "tmp"
+       assertEqual "split7" (ExitSuccess, "", "") result
+    where
+      f (Just (S.Ident "appTemplate")) = S.ModuleName "Route"
+      f (Just (S.Ident "Route")) = S.ModuleName "Route"
+      f (Just (S.Ident "route")) = S.ModuleName "Route"
+      f (Just (S.Ident "CtrlV")) = S.ModuleName "Route"
+      f (Just (S.Ident "CtrlV'")) = S.ModuleName "Route"
+      f (Just (S.Ident "CtrlVForm")) = S.ModuleName "Route"
+      f (Just (S.Ident "CtrlVState")) = S.ModuleName "Route"
+      f (Just (S.Ident "viewPastePage")) = S.ModuleName "Route"
+      f (Just (S.Ident "viewRecentPage")) = S.ModuleName "Route"
+      f (Just (S.Ident "newPastePage")) = S.ModuleName "Route"
+      f (Just (S.Ident "main")) = S.ModuleName "Main"
+      f (Just (S.Ident "PasteId")) = S.ModuleName "PasteId"
+      f (Just (S.Ident "Format")) = S.ModuleName "Format"
+      f (Just (S.Ident "PasteMeta")) = S.ModuleName "PasteMeta"
+      f (Just (S.Ident "Paste")) = S.ModuleName "Paste"
+      f (Just (S.Ident "initialCtrlVState,")) = S.ModuleName "InitialCtrlVState"
+      f (Just (S.Ident "insertPaste")) = S.ModuleName "InsertPaste"
+      f (Just (S.Ident "getPasteById")) = S.ModuleName "GetPasteById"
+      f (Just (S.Ident "Limit")) = S.ModuleName "Limit"
+      f (Just (S.Ident "Offset")) = S.ModuleName "Offset"
+      f (Just (S.Ident "getRecentPastes")) = S.ModuleName "GetRecentPastes"
+      f (Just (S.Ident "formatPaste")) = S.ModuleName "FormatPaste"
+      f (Just (S.Ident "pasteForm")) = S.ModuleName "PasteForm"
+      f Nothing = S.ModuleName "Route"
+      f _ = S.ModuleName "Other"
+
+split7b :: Test
+split7b =
+    TestLabel "split7b" $ TestCase $
+    do _ <- rsync "testdata/fold3b" "tmp"
+       _ <- withCurrentDirectory "tmp" $ runCleanT $
+            do putModule (S.ModuleName "Main")
+               extraImport (S.ModuleName "Main.GetPasteById") (S.ModuleName "Main.Instances")
+               extraImport (S.ModuleName "Main.GetRecentPastes") (S.ModuleName "Main.Instances")
+               extraImport (S.ModuleName "Main.InitialCtrlVState") (S.ModuleName "Main.Instances")
+               extraImport (S.ModuleName "Main.InsertPaste") (S.ModuleName "Main.Instances")
+               splitModuleDecls "Main.hs"
+       result <- diff "testdata/split7-expected" "tmp"
+       assertEqual "split7b" (ExitSuccess, "", "") result
diff --git a/Tests/SrcLoc.hs b/Tests/SrcLoc.hs
new file mode 100644
--- /dev/null
+++ b/Tests/SrcLoc.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE BangPatterns, FlexibleInstances, ScopedTypeVariables, UndecidableInstances #-}
+{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
+module Tests.SrcLoc where
+
+import Language.Haskell.Exts.SrcLoc (SrcLoc(..))
+import Language.Haskell.Modules.Util.SrcLoc (srcPairText)
+import Prelude hiding (rem)
+import Test.HUnit (assertEqual, Test(TestCase, TestList))
+
+tests :: Test
+tests = TestList [test1, test2, test3, test4, test5]
+
+test1 :: Test
+-- test1 = TestCase (assertEqual "srcPairTextTail1" "hi\tjkl\n" (snd (srcPairText (SrcLoc "<unknown>.hs" 1 10) (SrcLoc "<unknown>.hs" 2 2) "abc\tdef\nghi\tjkl\n")))
+test1 = TestCase (assertEqual "srcPairTextTail1" "hi\tjkl\n" (snd (srcPairText (SrcLoc "<unknown>.hs" 1 6) (SrcLoc "<unknown>.hs" 2 2) "abc\tdef\nghi\tjkl\n")))
+test2 :: Test
+test2 = TestCase (assertEqual "srcPairTextTail2" "" (snd (srcPairText (SrcLoc "<unknown>.hs" 1 4) (SrcLoc "<unknown>.hs" 3 1) "abc\tdef\nghi\tjkl\n")))
+test3 :: Test
+test3 = TestCase (assertEqual "srcPairTextHead1" "abc\tdef\ng" (fst (srcPairText (SrcLoc "<unknown>.hs" 1 10) (SrcLoc "<unknown>.hs" 2 2) "abc\tdef\nghi\tjkl\n")))
+test4 :: Test
+test4 = TestCase (assertEqual "srcPairTextHead21" "abc\tdef\nghi\t" (fst (srcPairText (SrcLoc "<unknown>.hs" 1 5) (SrcLoc "<unknown>.hs" 2 5) "abc\tdef\nghi\tjkl\n")))
+test5 :: Test
+test5 = TestCase (assertEqual "srcPairTextTail3"
+                              "{-# OPTIONS_GHC -fno-warn-orphans #-}\nmodule Debian.Repo.Orphans where\n\nimport Data.Text (Text)\nimport qualified Debian.Control.Text as T\n\nderiving instance Show (T.Field' Text)\nderiving instance Ord (T.Field' Text)\nderiving instance Show T.Paragraph\nderiving instance Ord T.Paragraph\n"
+                              (snd
+                               (srcPairText
+                                 (SrcLoc "<unknown>.hs" 1 77)
+                                 (SrcLoc "<unknown>.hs" 2 1)
+                                 "\n{-# OPTIONS_GHC -fno-warn-orphans #-}\nmodule Debian.Repo.Orphans where\n\nimport Data.Text (Text)\nimport qualified Debian.Control.Text as T\n\nderiving instance Show (T.Field' Text)\nderiving instance Ord (T.Field' Text)\nderiving instance Show T.Paragraph\nderiving instance Ord T.Paragraph\n")))
diff --git a/Tests/Symbols.hs b/Tests/Symbols.hs
new file mode 100644
--- /dev/null
+++ b/Tests/Symbols.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
+module Tests.Symbols
+    ( tests
+    , test1
+    , test2
+    , test3
+    , test4
+    ) where
+
+import Data.Set (fromList)
+import Language.Haskell.Exts.Annotated.Syntax as A -- (Decl(DefaultDecl, PatBind), Exp(Var), Name(Ident), Pat(PApp, PVar), QName(UnQual), Rhs(UnGuardedRhs), Type(TyVar))
+import Language.Haskell.Exts.Parser (parse, fromParseResult)
+import Language.Haskell.Exts.Pretty (prettyPrint)
+import Language.Haskell.Exts.SrcLoc (SrcSpan(..), SrcSpanInfo(..))
+import qualified Language.Haskell.Exts.Syntax as S
+import Language.Haskell.Modules.Util.SrcLoc ()
+import Language.Haskell.Modules.Util.Symbols (symbols, members)
+import Test.HUnit (assertEqual, Test(TestCase, TestList))
+
+tests :: Test
+tests = TestList [test1, test2, test3, test4, test5]
+
+test1 :: Test
+test1 = TestCase (assertEqual "DefaultDecl" " \ndefault (foo)" (prettyPrint (A.DefaultDecl def [A.TyVar def (A.Ident def "foo")] :: A.Decl SrcSpanInfo)))
+test2 :: Test
+test2 = TestCase (assertEqual "PatBind" "pvar :: typ = unqualrhs" (prettyPrint (A.PatBind def (A.PVar def (A.Ident def "pvar")) (Just (A.TyVar def (A.Ident def "typ"))) (A.UnGuardedRhs def (A.Var def (A.UnQual def (A.Ident def "unqualrhs")))) Nothing :: A.Decl SrcSpanInfo)))
+test3 :: Test
+test3 = TestCase (assertEqual "Pat" "pvar" (prettyPrint (A.PVar def (A.Ident def "pvar") :: A.Pat SrcSpanInfo)))
+test4 :: Test
+test4 = TestCase (assertEqual "Pat" "unqual pvar" (prettyPrint (A.PApp def (A.UnQual def (A.Ident def "unqual")) [A.PVar def (A.Ident def "pvar")] :: A.Pat SrcSpanInfo)))
+
+test5 :: Test
+test5 =
+    TestCase (assertEqual "symbols DataDecl" expected (symbols decl, members decl))
+    where
+      expected = (-- Type name
+                  fromList [Just (S.Ident "Paste")],
+                  -- Constructor and field accessors
+                  fromList [Just (S.Ident "Paste"), Just (S.Ident "pasteMeta"), Just (S.Ident "paste")])
+      decl :: A.Decl SrcSpanInfo
+      decl = fromParseResult $ parse $ unlines [ "data Paste = Paste"
+                                               , "    { pasteMeta :: PasteMeta"
+                                               , "    , paste     :: Text"
+                                               , "    }"
+                                               , "    deriving (Eq, Ord, Read, Show, Data, Typeable)" ]
+
+def :: SrcSpanInfo
+def = SrcSpanInfo (SrcSpan "test" 1 1 1 1) []
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,20 @@
+haskell-module-management (0.15) unstable; urgency=low
+
+  * Implement parsing of files which need the XmlSyntax extension (e.g. files
+    that need the hsx2hs preprocessor.)
+  * Add extraImport m i, which insert an import of module i when
+    generating module m.
+  * Use lifted-base and monad-control instead of the deprecated library
+    MonadCatchIO-mtl.
+
+ -- David Fox <dsf@seereason.com>  Fri, 19 Jul 2013 09:52:38 -0700
+
+haskell-module-management (0.14) unstable; urgency=low
+
+  * Use ModuleName type in some places where were were using String.
+
+ -- David Fox <dsf@seereason.com>  Wed, 17 Jul 2013 11:10:49 -0700
+
 haskell-module-management (0.13) unstable; urgency=low
 
   * Changed cleanImports and cleanResults functions to take a list of
diff --git a/module-management.cabal b/module-management.cabal
--- a/module-management.cabal
+++ b/module-management.cabal
@@ -1,5 +1,5 @@
 Name:               module-management
-Version:            0.13
+Version:            0.15
 Synopsis:           Clean up module imports, split and merge modules
 Description:        Clean up module imports, split and merge modules.
 Homepage:           http://src.seereason.com/module-management
@@ -35,11 +35,12 @@
     Language.Haskell.Modules.Util.Temp,
     Language.Haskell.Modules.Util.Test
   Other-Modules:
-    Language.Haskell.Modules.Internal,
     Tests.Fold,
     Tests.Imports,
     Tests.Merge,
     Tests.Split
+    Tests.SrcLoc
+    Tests.Symbols
   Build-Depends:
     applicative-extras,
     base >= 4 && < 5,
@@ -51,7 +52,8 @@
     filepath,
     haskell-src-exts,
     HUnit,
-    MonadCatchIO-mtl,
+    lifted-base,
+    monad-control,
     mtl,
     pretty,
     process,
@@ -71,8 +73,9 @@
     filepath,
     haskell-src-exts,
     HUnit,
+    lifted-base,
     module-management,
-    MonadCatchIO-mtl,
+    monad-control,
     mtl,
     process,
     set-extra,
@@ -96,8 +99,9 @@
       filepath,
       HUnit,
       haskell-src-exts,
+      monad-control,
       module-management,
-      MonadCatchIO-mtl,
+      lifted-base,
       mtl,
       process,
       process-progress,
diff --git a/scripts/CLI.hs b/scripts/CLI.hs
--- a/scripts/CLI.hs
+++ b/scripts/CLI.hs
@@ -5,7 +5,6 @@
 import Control.Monad.Trans (MonadIO(liftIO))
 import Data.List (intercalate, isPrefixOf)
 import Data.Set.Extra as Set (Set, toList)
-import Language.Haskell.Exts.Syntax (ModuleName(ModuleName))
 import Language.Haskell.Modules
 import Language.Haskell.Modules.ModuVerse (getNames)
 import Language.Haskell.Modules.SourceDirs (getDirs)
@@ -60,7 +59,7 @@
       find s =
           do ms <- liftIO (findHsModules [s])
              case ms of
-               [] -> return [s]
+               [] -> return [ModuleName s]
                _ -> return ms
 
 showVerse :: Set ModuleName -> String
diff --git a/testdata.tar.gz b/testdata.tar.gz
Binary files a/testdata.tar.gz and b/testdata.tar.gz differ
