diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -3,15 +3,17 @@
     main ) where
 
 import           Data.Maybe
-import qualified Data.Text           as T
-import qualified Data.Text.Lazy      as TL
-import qualified Data.Text.Lazy.IO   as TLIO
+import           Data.Semigroup
+import qualified Data.Text                    as T
+import qualified Data.Text.Lazy               as TL
+import qualified Data.Text.Lazy.IO            as TLIO
 import           Data.Version
-import           Options.Applicative hiding (ParseError)
+import           Options.Applicative          hiding (ParseError)
 import           Paths_madlang
 import           System.Directory
 import           Text.Madlibs
-import           Text.Megaparsec     hiding (many)
+import           Text.Madlibs.Packaging.Fetch
+import           Text.Megaparsec              hiding (many)
 
 -- | datatype for the program
 newtype Program = Program { sub :: Subcommand }
diff --git a/app/Text/Madlibs/Packaging/Fetch.hs b/app/Text/Madlibs/Packaging/Fetch.hs
new file mode 100644
--- /dev/null
+++ b/app/Text/Madlibs/Packaging/Fetch.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Text.Madlibs.Packaging.Fetch ( fetchGithub
+                                    , fetchPackages
+                                    , cleanPackages
+                                    , installVimPlugin
+                                    ) where
+
+import qualified Codec.Archive.Tar       as Tar
+import           Codec.Archive.Zip       (ZipOption (..),
+                                          extractFilesFromArchive, toArchive)
+import           Codec.Compression.GZip  (decompress)
+import           Control.Monad           (unless)
+import           Network.HTTP.Client     hiding (decompress)
+import           Network.HTTP.Client.TLS (tlsManagerSettings)
+import           System.Directory        (removeFile, renameDirectory)
+import           System.Environment      (getEnv)
+import           System.Info             (os)
+
+-- https://hub.darcs.net/vmchale/madlang-libraries/dist
+
+invalid :: String -> Bool
+invalid = not . ('/' `elem`)
+
+-- | As an example, `vmchale/some-library` would be valid input.
+fetchGithub :: String -> IO ()
+fetchGithub s = unless (invalid s) $ do
+
+    putStrLn $ "fetching library at " ++ s
+
+    manager <- newManager tlsManagerSettings
+    initialRequest <- parseRequest $ "https://github.com/" ++ s ++ "/archive/master.zip"
+    response <- responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
+
+    putStrLn "unpacking libraries..."
+    home <- getEnv "HOME"
+    let packageDir = if os /= "mingw32" then home ++ "/.madlang" else home ++ "\\.madlang"
+    let options = OptDestination packageDir
+    extractFilesFromArchive [options] (toArchive response)
+
+    let repoName = filter (/='/') . dropWhile (/='/') $ s
+    renameDirectory (packageDir ++ "/" ++ repoName ++ "-master") (packageDir ++ "/" ++ repoName)
+
+installVimPlugin :: IO ()
+installVimPlugin = do
+
+    putStrLn "fetching latest vim plugin..."
+    manager <- newManager defaultManagerSettings
+    initialRequest <- parseRequest "http://vmchale.com/static/vim.zip"
+    response <- responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
+
+    putStrLn "installing locally..."
+    home <- getEnv "HOME"
+    let packageDir = if os /= "mingw32" then home ++ "/.vim" else home ++ "\\vimfiles"
+    let options = OptDestination packageDir
+    extractFilesFromArchive [options] (toArchive response)
+
+    putStrLn "cleaning junk..."
+    removeFile (packageDir ++ "/TODO.md")
+    removeFile (packageDir ++ "/vim-screenshot.png")
+    removeFile (packageDir ++ "/README.md")
+    removeFile (packageDir ++ "/LICENSE")
+
+-- TODO set remote package url flexibly
+fetchPackages :: IO ()
+fetchPackages = do
+
+    putStrLn "fetching libraries..."
+    manager <- newManager defaultManagerSettings
+    initialRequest <- parseRequest "http://vmchale.com/static/packages.tar.gz"
+    response <- responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
+
+    putStrLn "unpacking libraries..."
+    home <- getEnv "HOME"
+    let packageDir = if os /= "mingw32" then home ++ "/.madlang" else home ++ "\\.madlang"
+    Tar.unpack packageDir . Tar.read . decompress $ response
+
+cleanPackages :: IO ()
+cleanPackages =
+    putStrLn "done."
diff --git a/cabal.project.local b/cabal.project.local
--- a/cabal.project.local
+++ b/cabal.project.local
@@ -1,4 +1,2 @@
-tests: true
-benchmarks: true
-documentation: true
 constraints: madlang +development
+max-backjumps: 120000
diff --git a/madlang.cabal b/madlang.cabal
--- a/madlang.cabal
+++ b/madlang.cabal
@@ -1,6 +1,6 @@
 cabal-version: >=1.10
 name: madlang
-version: 4.0.2.7
+version: 4.0.2.8
 license: BSD3
 license-file: LICENSE
 copyright: Copyright: (c) 2016-2018 Vanessa McHale
@@ -58,11 +58,10 @@
         Text.Madlibs.Internal.Utils
         Text.Madlibs.Cata.SemErr
         Text.Madlibs.Cata.Display
-        Text.Madlibs.Packaging.Fetch
     default-language: Haskell2010
     ghc-options: -Wall
     build-depends:
-        base >=4.11 && <5,
+        base >=4.9 && <5,
         megaparsec >=6.0,
         text -any,
         template-haskell -any,
@@ -76,11 +75,6 @@
         containers -any,
         titlecase >=1.0,
         th-lift-instances -any,
-        http-client -any,
-        http-client-tls -any,
-        tar -any,
-        zlib -any,
-        zip-archive -any,
         recursion-schemes -any,
         binary -any
     
@@ -95,15 +89,21 @@
     hs-source-dirs: app
     other-modules:
         Paths_madlang
+        Text.Madlibs.Packaging.Fetch
     default-language: Haskell2010
     ghc-options: -Wall
     build-depends:
-        base >=4.11,
+        base >=4.9,
         madlang -any,
         optparse-applicative -any,
         text -any,
         directory -any,
-        megaparsec -any
+        megaparsec -any,
+        http-client -any,
+        tar -any,
+        zlib -any,
+        zip-archive -any,
+        http-client-tls -any
     
     if flag(library)
         buildable: False
diff --git a/src/Text/Madlibs.hs b/src/Text/Madlibs.hs
--- a/src/Text/Madlibs.hs
+++ b/src/Text/Madlibs.hs
@@ -40,10 +40,6 @@
                     , runFileN
                     , getDir
                     , displayTree
-                    , fetchPackages
-                    , cleanPackages
-                    , fetchGithub
-                    , installVimPlugin
                     -- * Template Haskell EDSL
                     , madlang
                     , madFile
@@ -57,4 +53,3 @@
 import           Text.Madlibs.Generate.TH
 import           Text.Madlibs.Internal.Types
 import           Text.Madlibs.Internal.Utils
-import           Text.Madlibs.Packaging.Fetch
diff --git a/src/Text/Madlibs/Ana/Parse.hs b/src/Text/Madlibs/Ana/Parse.hs
--- a/src/Text/Madlibs/Ana/Parse.hs
+++ b/src/Text/Madlibs/Ana/Parse.hs
@@ -17,6 +17,7 @@
 import           Control.Monad.State
 import qualified Data.Map                    as M
 import           Data.Maybe
+import           Data.Semigroup
 import qualified Data.Text                   as T
 import           Data.Void
 import           Text.Madlibs.Ana.ParseUtils
diff --git a/src/Text/Madlibs/Ana/ParseUtils.hs b/src/Text/Madlibs/Ana/ParseUtils.hs
--- a/src/Text/Madlibs/Ana/ParseUtils.hs
+++ b/src/Text/Madlibs/Ana/ParseUtils.hs
@@ -18,7 +18,8 @@
 import           Data.Foldable
 import           Data.List
 import qualified Data.Map                    as M
-import           Data.Maybe                  (catMaybes)
+import           Data.Maybe                  (mapMaybe)
+import           Data.Semigroup
 import qualified Data.Set                    as S
 import qualified Data.Text                   as T
 import           Data.Text.Titlecase
@@ -108,7 +109,7 @@
 maybeList Nothing  = []
 
 allDeps :: M.Map Key [(Prob, [PreTok])] -> Key -> S.Set Key
-allDeps context key = let deps = (maybeList . fmap (catMaybes . fmap maybeName) . getNames) context in S.fromList (deps <> (S.toList . allDeps context =<< deps))
+allDeps context key = let deps = (maybeList . fmap (mapMaybe maybeName) . getNames) context in S.fromList (deps <> (S.toList . allDeps context =<< deps))
     where getNames = fmap ((=<<) snd) . M.lookup key
           maybeName (Name n _) = Just n
           maybeName _          = Nothing
diff --git a/src/Text/Madlibs/Ana/Resolve.hs b/src/Text/Madlibs/Ana/Resolve.hs
--- a/src/Text/Madlibs/Ana/Resolve.hs
+++ b/src/Text/Madlibs/Ana/Resolve.hs
@@ -18,6 +18,7 @@
 import           Control.Monad               (replicateM, void)
 import           Control.Monad.IO.Class      (MonadIO, liftIO)
 import           Control.Monad.Random.Class
+import           Data.Semigroup
 import qualified Data.Text                   as T
 import           Data.Void
 import           System.Directory
diff --git a/src/Text/Madlibs/Generate/TH.hs b/src/Text/Madlibs/Generate/TH.hs
--- a/src/Text/Madlibs/Generate/TH.hs
+++ b/src/Text/Madlibs/Generate/TH.hs
@@ -12,6 +12,7 @@
 
 import           Control.Arrow               (first)
 import           Data.FileEmbed              (embedStringFile)
+import           Data.Semigroup
 import qualified Data.Text                   as T
 import qualified Data.Text.IO                as TIO
 import           Data.Void
diff --git a/src/Text/Madlibs/Internal/Types.hs b/src/Text/Madlibs/Internal/Types.hs
--- a/src/Text/Madlibs/Internal/Types.hs
+++ b/src/Text/Madlibs/Internal/Types.hs
@@ -18,6 +18,7 @@
 import           Data.Binary                (Binary)
 import           Data.Function
 import           Data.Functor.Foldable.TH   (makeBaseFunctor)
+import           Data.Semigroup
 import qualified Data.Text                  as T
 import           GHC.Generics               (Generic)
 import           Instances.TH.Lift          ()
@@ -61,6 +62,7 @@
 -- > (List [(0.5,"Hello you"), (0.5, "Hello me")])
 instance Monoid RandTok where
     mempty = Value ""
+    mappend = (<>)
 
 -- TODO make this a map instead of keys for faster parse.
 -- | State monad providing context, i.e. function we've already called before
diff --git a/src/Text/Madlibs/Packaging/Fetch.hs b/src/Text/Madlibs/Packaging/Fetch.hs
deleted file mode 100644
--- a/src/Text/Madlibs/Packaging/Fetch.hs
+++ /dev/null
@@ -1,80 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Madlibs.Packaging.Fetch ( fetchGithub
-                                    , fetchPackages
-                                    , cleanPackages
-                                    , installVimPlugin
-                                    ) where
-
-import qualified Codec.Archive.Tar       as Tar
-import           Codec.Archive.Zip       (ZipOption (..),
-                                          extractFilesFromArchive, toArchive)
-import           Codec.Compression.GZip  (decompress)
-import           Control.Monad           (unless)
-import           Network.HTTP.Client     hiding (decompress)
-import           Network.HTTP.Client.TLS (tlsManagerSettings)
-import           System.Directory        (removeFile, renameDirectory)
-import           System.Environment      (getEnv)
-import           System.Info             (os)
-
--- https://hub.darcs.net/vmchale/madlang-libraries/dist
-
-invalid :: String -> Bool
-invalid = not . ('/' `elem`)
-
--- | As an example, `vmchale/some-library` would be valid input.
-fetchGithub :: String -> IO ()
-fetchGithub s = unless (invalid s) $ do
-
-    putStrLn $ "fetching library at " ++ s
-
-    manager <- newManager tlsManagerSettings
-    initialRequest <- parseRequest $ "https://github.com/" ++ s ++ "/archive/master.zip"
-    response <- responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
-
-    putStrLn "unpacking libraries..."
-    home <- getEnv "HOME"
-    let packageDir = if os /= "mingw32" then home ++ "/.madlang" else home ++ "\\.madlang"
-    let options = OptDestination packageDir
-    extractFilesFromArchive [options] (toArchive response)
-
-    let repoName = filter (/='/') . dropWhile (/='/') $ s
-    renameDirectory (packageDir ++ "/" ++ repoName ++ "-master") (packageDir ++ "/" ++ repoName)
-
-installVimPlugin :: IO ()
-installVimPlugin = do
-
-    putStrLn "fetching latest vim plugin..."
-    manager <- newManager defaultManagerSettings
-    initialRequest <- parseRequest "http://vmchale.com/static/vim.zip"
-    response <- responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
-
-    putStrLn "installing locally..."
-    home <- getEnv "HOME"
-    let packageDir = if os /= "mingw32" then home ++ "/.vim" else home ++ "\\vimfiles"
-    let options = OptDestination packageDir
-    extractFilesFromArchive [options] (toArchive response)
-
-    putStrLn "cleaning junk..."
-    removeFile (packageDir ++ "/TODO.md")
-    removeFile (packageDir ++ "/vim-screenshot.png")
-    removeFile (packageDir ++ "/README.md")
-    removeFile (packageDir ++ "/LICENSE")
-
--- TODO set remote package url flexibly
-fetchPackages :: IO ()
-fetchPackages = do
-
-    putStrLn "fetching libraries..."
-    manager <- newManager defaultManagerSettings
-    initialRequest <- parseRequest "http://vmchale.com/static/packages.tar.gz"
-    response <- responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
-
-    putStrLn "unpacking libraries..."
-    home <- getEnv "HOME"
-    let packageDir = if os /= "mingw32" then home ++ "/.madlang" else home ++ "\\.madlang"
-    Tar.unpack packageDir . Tar.read . decompress $ response
-
-cleanPackages :: IO ()
-cleanPackages =
-    putStrLn "done."
