diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,30 +1,36 @@
-### 0.7.0.7 (unreleased)
+### 0.7.0.8
 
+- Add support for `containers-0.7` [#58](https://github.com/docopt/docopt.hs/pull/58), [#60](https://github.com/docopt/docopt.hs/pull/60)
+
+- Extend Template Haskell Quasi-quotation support to GHC 8.0-8.6. Template Haskell support is no longer optional. The package now supports all GHC's from 8.0 to 9.8. [#56](https://github.com/docopt/docopt.hs/pull/56), [#58](https://github.com/docopt/docopt.hs/pull/58)
+
+### 0.7.0.7
+
 - update bounds, fix warnings, require ghc 8.0+
 
 ### 0.7.0.6
 
-- Fixes issue causing compilation error to happen with ghc-8.8.2 [#33][#34]
+- Fixes issue causing compilation error to happen with ghc-8.8.2 [#33](https://github.com/docopt/docopt.hs/issues/33), [#34](https://github.com/docopt/docopt.hs/pull/34)
 
 ### 0.7.0.5
 
-- Fix an issue where in some cases pattern lines were matched out of order [#16]
-- Strip leading & trailing newlines from usage, for quasiquoter ease [#28]
-- Fix tests run against latest aeson 1.0.2.0 [#29]
+- Fix an issue where in some cases pattern lines were matched out of order [#16](https://github.com/docopt/docopt.hs/issues/16)
+- Strip leading & trailing newlines from usage, for quasiquoter ease [#28](https://github.com/docopt/docopt.hs/issues/28)
+- Fix tests run against latest aeson 1.0.2.0 [#29](https://github.com/docopt/docopt.hs/issues/29)
 
 ### 0.7.0.4
 
-- Fix the test suite when run from a distributed tarball [#21]
+- Fix the test suite when run from a distributed tarball [#21](https://github.com/docopt/docopt.hs/pull/21)
 - Make the test suite more developer-friendly
 
 ### 0.7.0.3
 
-- Fix `isPresent` treatment of repeatable arguments/options [#15]
-- Fix build failure for stackage inclusion [#20]
+- Fix `isPresent` treatment of repeatable arguments/options [#15](https://github.com/docopt/docopt.hs/issues/15)
+- Fix build failure for stackage inclusion [#20](https://github.com/docopt/docopt.hs/pull/20)
 
 ### 0.7.0.2
 
-- Minor docs/README tweaks [#13]
+- Minor docs/README tweaks [#13](https://github.com/docopt/docopt.hs/issues/13)
 
 ### 0.7.0.1
 
@@ -32,13 +38,13 @@
 
 # 0.7.0.0
 
-- Add usage parsing QuasiQuoters [#7]
+- Add usage parsing QuasiQuoters [#7](https://github.com/docopt/docopt.hs/pull/7)
   - Add `docopt` usage parsing QuasiQuoter
   - Add `docoptFile` usage parsing QuasiQuoter
   - Add `System.Docopt.NoTH` module
     - Add `parseUsage`
     - Add `parseUsageOrExit`
-- New API organization [#10]
+- New API organization [#10](https://github.com/docopt/docopt.hs/issues/10)
   - Remove `optionsWithUsage`
   - Remove `optionsWithUsageDebug`
   - Remove `optionsWithUsageFile`
@@ -59,7 +65,7 @@
   
 ### 0.6.0.2
 
-- Make `argument` not require its named option wrapped in angle brackets. [#4, #5]
+- Make `argument` not require its named option wrapped in angle brackets. [#4](https://github.com/docopt/docopt.hs/pull/4), [#5](https://github.com/docopt/docopt.hs/pull/5)
 
 ### 0.6.0.1
 
diff --git a/System/Console/Docopt/OptParse.hs b/System/Console/Docopt/OptParse.hs
--- a/System/Console/Docopt/OptParse.hs
+++ b/System/Console/Docopt/OptParse.hs
@@ -1,3 +1,5 @@
+{-# OPTIONS_GHC -Wno-unused-do-bind #-}
+
 module System.Console.Docopt.OptParse
   where
 
@@ -15,7 +17,7 @@
 --   @fmt@ is the OptPattern together with metadata to tell the parser how to parse args.
 --   Together, these let @buildOptParser@ build a parsec parser that can be applied to an argv.
 buildOptParser :: String -> OptFormat -> CharParser OptParserState ()
-buildOptParser delim fmt@(pattern, infomap) =
+buildOptParser delim (pattern, infomap) =
 
   let -- Helpers
       argDelim = (try $ string delim) <?> "space between arguments"
@@ -124,7 +126,7 @@
                 unorderedSynParser = buildOptParser delim (Unordered oneOfSyns, infomap)
             in  unorderedSynParser
                 <?> humanize o
-      o@(Argument name) ->
+      o@(Argument _name) ->
             do val <- try $ many1 (notFollowedBy argDelim >> anyChar)
                updateSt_saveOccurrence o val
                updateSt_inShortOptStack False
@@ -157,7 +159,7 @@
             Just oldval -> newval `updateFrom` oldval
           updateFrom newval oldval = Just $ case oldval of
             MultiValue vs -> MultiValue $ newval : vs
-            Value v       -> Value newval
+            Value _v      -> Value newval
             NoValue       -> Value newval
             Counted n     -> Counted (n+1)
             Present       -> Present
@@ -185,10 +187,10 @@
 optInitialValue info opt =
   let repeatable = isRepeated info
   in case opt of
-    Command name  -> Just $ if repeatable then Counted 0 else NotPresent
-    Argument name -> Just $ if repeatable then MultiValue [] else NoValue
-    AnyOption     -> Nothing -- no storable value for [options] shortcut
-    _             -> case expectsVal info of
+    Command _name  -> Just $ if repeatable then Counted 0 else NotPresent
+    Argument _name -> Just $ if repeatable then MultiValue [] else NoValue
+    AnyOption      -> Nothing -- no storable value for [options] shortcut
+    _              -> case expectsVal info of
       True  -> Just $ if repeatable then MultiValue [] else NoValue
       False -> Just $ if repeatable then Counted 0 else NotPresent
 
@@ -196,10 +198,10 @@
 optDefaultValue info opt =
   let repeatable = isRepeated info
   in case opt of
-    Command name  -> Just $ if repeatable then Counted 0 else NotPresent
-    Argument name -> Just $ if repeatable then MultiValue [] else NoValue
-    AnyOption     -> Nothing -- no storable value for [options] shortcut
-    _               -> case expectsVal info of
+    Command _name  -> Just $ if repeatable then Counted 0 else NotPresent
+    Argument _name -> Just $ if repeatable then MultiValue [] else NoValue
+    AnyOption      -> Nothing -- no storable value for [options] shortcut
+    _              -> case expectsVal info of
       True  -> case defaultVal info of
         Just dval -> Just $ if repeatable
                             then MultiValue $ reverse $ words dval
diff --git a/System/Console/Docopt/ParseUtils.hs b/System/Console/Docopt/ParseUtils.hs
--- a/System/Console/Docopt/ParseUtils.hs
+++ b/System/Console/Docopt/ParseUtils.hs
@@ -31,8 +31,7 @@
 caseInsensitive = mapM (\c -> char (toLower c) <|> char (toUpper c))
 
 lookAhead_ :: CharParser u a -> CharParser u ()
-lookAhead_ p = do lookAhead p
-                  return ()
+lookAhead_ p = lookAhead p >> return ()
 
 isNotFollowedBy :: Show a => CharParser u a -> CharParser u Bool
 isNotFollowedBy p = option False (notFollowedBy p >> return True)
@@ -77,8 +76,8 @@
   rest <- manyTill p end
   return $ first : rest
 
--- |@skipUntil p@ ignores everything that comes before `p`.
--- Returns what `p` returns.
+-- |@skipUntil p@ ignores everything that comes before @p@.
+-- Returns what @p@ returns.
 skipUntil :: Show a => CharParser u a -> CharParser u ()
 skipUntil p = skipMany (notFollowedBy p >> anyChar)
 
diff --git a/System/Console/Docopt/Public.hs b/System/Console/Docopt/Public.hs
--- a/System/Console/Docopt/Public.hs
+++ b/System/Console/Docopt/Public.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 module System.Console.Docopt.Public
   (
     -- * Command line arguments parsers
@@ -42,6 +44,10 @@
 
 import System.Exit
 
+#if !MIN_VERSION_base(4,13,0)
+import Control.Monad.Fail (MonadFail)
+#endif
+
 import Data.Map as M hiding (null)
 import Data.Maybe (fromMaybe)
 import System.Console.Docopt.Types
@@ -101,7 +107,7 @@
 -- > Usage:
 -- >   prog <required>
 --
---   then @getArg args (argument \'required\')@ is guaranteed to be a 'Just'.
+--   then @getArg args (argument "required")@ is guaranteed to be a 'Just'.
 getArg :: Arguments -> Option -> Maybe String
 getArg args opt =
   case opt `M.lookup` args of
diff --git a/System/Console/Docopt/QQ/Instances.hs b/System/Console/Docopt/QQ/Instances.hs
--- a/System/Console/Docopt/QQ/Instances.hs
+++ b/System/Console/Docopt/QQ/Instances.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveLift#-}
 {-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE FlexibleInstances #-}
@@ -9,7 +10,10 @@
 
 import System.Console.Docopt.Types
 import Language.Haskell.TH.Syntax (Lift)
-import Data.Map.Internal (Map(..))
 
+#if !MIN_VERSION_containers(0,6,6)
+import Data.Map.Internal (Map(..))
 deriving instance Lift (Map Option OptionInfo)
+#endif
+
 deriving instance Lift (Docopt)
diff --git a/System/Console/Docopt/UsageParse.hs b/System/Console/Docopt/UsageParse.hs
--- a/System/Console/Docopt/UsageParse.hs
+++ b/System/Console/Docopt/UsageParse.hs
@@ -1,3 +1,5 @@
+{-# OPTIONS_GHC -Wno-unused-do-bind #-}
+
 module System.Console.Docopt.UsageParse
   where
 
@@ -71,9 +73,9 @@
         firstPairs = map (\x -> (x,False)) firstChars
         lastPair = (lastChar, lastExpectsVal)
     saveOptionsExpectVal ShortOption (firstPairs ++ [lastPair])
-    case length chars of
-      0 -> fail ""
-      1 -> return $ Atom . ShortOption $ head chars
+    case chars of
+      []  -> fail ""
+      [c] -> return $ Atom . ShortOption $ c
       _ -> return $ Unordered $ map (Atom . ShortOption) chars
 
 pLongOption :: CharParser OptInfoMap (Name, Bool)
@@ -97,9 +99,9 @@
 pArgument :: CharParser OptInfoMap String
 pArgument = try bracketStyle <|> try upperStyle
             where bracketStyle = do
-                      open <- char '<'
+                      _open <- char '<'
                       name <- many $ oneOf alphanumSpecial
-                      close <- char '>'
+                      _close <- char '>'
                       return name
                   upperStyle = do
                       first <- oneOf uppers
@@ -156,7 +158,7 @@
 -- * Option Synonyms & Defaults Parsers
 
 -- | Succeeds only on the first line of an option explanation
---   (one whose first non-space character is '-')
+--   (one whose first non-space character is @\'-\'@)
 begOptionLine :: CharParser OptInfoMap String
 begOptionLine = inlineSpaces >> lookAhead (char '-') >> return "-"
 
@@ -224,15 +226,16 @@
 expectSynonyms oim (Unordered exs) = Unordered $ map (expectSynonyms oim) exs
 expectSynonyms oim (Optional ex)   = Optional $ expectSynonyms oim ex
 expectSynonyms oim (Repeated ex)   = Repeated $ expectSynonyms oim ex
-expectSynonyms oim a@(Atom atom)   = case atom of
-    e@(Command ex)     -> a
-    e@(Argument ex)    -> a
-    e@AnyOption        -> flatten $ Unordered $ nub $ map Atom $ concatMap synonyms (M.elems oim)
-    e@(LongOption ex)  ->
+expectSynonyms oim a@(Atom atom)   =
+  case atom of
+    Command _ex      -> a
+    Argument _ex     -> a
+    AnyOption        -> flatten $ Unordered $ nub $ map Atom $ concatMap synonyms (M.elems oim)
+    e@(LongOption _ex) ->
         case synonyms <$> e `M.lookup` oim of
           Just syns -> flatten . OneOf $ map Atom syns
           Nothing -> a
-    e@(ShortOption c)  ->
+    e@(ShortOption _c) ->
         case synonyms <$> e `M.lookup` oim of
           Just syns -> flatten . OneOf $ map Atom syns
           Nothing -> a
@@ -244,8 +247,8 @@
     (OneOf ps)     -> canRepeatInside ps
     (Unordered ps) -> canRepeatInside ps || (atomicOccurrences ps > 1)
     (Optional p)   -> canRepeat p target
-    (Repeated p)   -> target `elem` atoms pat
-    (Atom a)       -> False
+    (Repeated _p)  -> target `elem` atoms pat
+    (Atom _a)      -> False
   where canRepeatInside = any (`canRepeat` target)
         atomicOccurrences ps = length $ filter (== target) $ atoms $ Sequence ps
 
@@ -253,22 +256,25 @@
 -- | Compare on specificity of parsers built from optA and optB,
 --   so we can be sure the parser tries the most-specific first, where possible.
 --   E.g.
---     LongOption "option" > ShortOption 'o' == True
---     Command "cmd" > Argument "arg"        == True
+--
+-- @
+-- LongOption "option" > ShortOption \'o\' == True
+-- Command "cmd" > Argument "arg"        == True
+-- @
 compareOptSpecificity :: Option -> Option -> Ordering
 compareOptSpecificity optA optB = case optA of
     LongOption a  -> case optB of
       LongOption b  -> comparingFirst length a b
       _             -> GT
     ShortOption a -> case optB of
-      LongOption b  -> LT
+      LongOption _b -> LT
       ShortOption b -> compare a b
       _             -> GT
     Command a     -> case optB of
-      LongOption b  -> LT
-      ShortOption b -> LT
-      Command b     -> comparingFirst length a b
-      _             -> GT
+      LongOption _b  -> LT
+      ShortOption _b -> LT
+      Command b      -> comparingFirst length a b
+      _              -> GT
     Argument a    -> case optB of
       AnyOption     -> GT
       Argument b    -> comparingFirst length a b
@@ -307,12 +313,13 @@
 
     representativeAtom :: OptPattern -> Option
     representativeAtom p = case p of
-      Sequence ps  -> if null ps then AnyOption else representativeAtom $ head ps
-      OneOf ps     -> maximumBy compareOptSpecificity . map representativeAtom $ ps
-      Unordered ps -> maximumBy compareOptSpecificity . map representativeAtom $ ps
-      Optional p   -> representativeAtom p
-      Repeated p   -> representativeAtom p
-      Atom a       -> a
+      Sequence []    -> AnyOption
+      Sequence (p:_) -> representativeAtom p
+      OneOf ps       -> maximumBy compareOptSpecificity . map representativeAtom $ ps
+      Unordered ps   -> maximumBy compareOptSpecificity . map representativeAtom $ ps
+      Optional p     -> representativeAtom p
+      Repeated p     -> representativeAtom p
+      Atom a         -> a
 
     maxLength :: OptPattern -> Int
     maxLength p = case p of
@@ -325,5 +332,5 @@
         LongOption o  -> length o
         ShortOption _ -> 1
         Command c     -> length c
-        Argument a    -> 100
+        Argument _a   -> 100
         AnyOption     -> 0
diff --git a/docopt.cabal b/docopt.cabal
--- a/docopt.cabal
+++ b/docopt.cabal
@@ -1,13 +1,25 @@
 name:                docopt
-version:             0.7.0.7
+version:             0.7.0.8
 synopsis:            A command-line interface parser that will make you smile
 description:         Docopt parses command-line interface usage text that adheres to a familiar syntax, and from it builds a command-line argument parser that will ensure your program is invoked correctly with the available options specified in the usage text. This allows the developer to write a usage text and get an argument parser for free.
 
 license:             MIT
 license-file:        LICENSE.txt
 author:              Ryan Artecona
-maintainer:          ryanartecona@gmail.com
+maintainer:          QBayLogic B.V. <devops@qbaylogic.com>
 copyright:           (c) 2013-2015 Ryan Artecona
+tested-with:
+  GHC == 8.0.2,
+  GHC == 8.2.2,
+  GHC == 8.4.4,
+  GHC == 8.6.5,
+  GHC == 8.8.4,
+  GHC == 8.10.7,
+  GHC == 9.0.2,
+  GHC == 9.2.8,
+  GHC == 9.4.7,
+  GHC == 9.6.3,
+  GHC == 9.8.1
 
 category:            Console
 
@@ -27,14 +39,14 @@
   type:       git
   location:   https://github.com/docopt/docopt.hs.git
 
-flag template-haskell
-  default:      True
-  manual:       True
-  description:
-    Build with QuasiQuoter usage parsers, which requires Template Haskell
+source-repository this
+  type:       git
+  location:   https://github.com/docopt/docopt.hs.git
+  tag:        v0.7.0.8
 
 library
   exposed-modules:    System.Console.Docopt.NoTH
+                      System.Console.Docopt
 
   other-modules:      System.Console.Docopt.ApplicativeParsec
                       System.Console.Docopt.ParseUtils
@@ -42,22 +54,15 @@
                       System.Console.Docopt.UsageParse
                       System.Console.Docopt.OptParse
                       System.Console.Docopt.Public
+                      System.Console.Docopt.QQ
+                      System.Console.Docopt.QQ.Instances
 
   build-depends:      base >= 4.9 && < 5.0,
                       parsec >= 3.1.14 && < 3.2,
-                      containers >= 0.6.2 && < 0.7
-
-  ghc-options:        -Wall
-                      -fno-warn-unused-binds
-                      -fno-warn-unused-do-bind
-                      -fno-warn-unused-matches
-                      -fno-warn-name-shadowing
+                      containers >= 0.6.2 && < 0.8,
+                      template-haskell >= 2.11.0 && < 2.22
 
-  if impl(ghc >= 6.10) && flag(template-haskell)
-    exposed-modules:  System.Console.Docopt
-    other-modules:    System.Console.Docopt.QQ
-                      System.Console.Docopt.QQ.Instances
-    build-depends:    template-haskell >= 2.15.0 && < 2.18
+  ghc-options:        -Wall -Wno-name-shadowing
 
   default-language:   Haskell2010
 
@@ -66,25 +71,19 @@
   hs-source-dirs:     ./, test
   main-is:            LangAgnosticTests.hs
 
-  ghc-options:        -Wall
-                      -fno-warn-unused-binds
-                      -fno-warn-unused-do-bind
-                      -fno-warn-unused-matches
-                      -fno-warn-name-shadowing
-                      -fno-warn-orphans
+  ghc-options:        -Wall -Wno-name-shadowing
 
   build-depends:      base,
-                      parsec >= 3.1.14 && < 3.2,
-                      containers >= 0.6.2 && < 0.7,
+                      parsec,
+                      containers,
                       docopt,
                       HUnit,
                       split,
-                      ansi-terminal,
+                      ansi-terminal >= 0.4,
                       aeson,
                       bytestring,
                       text,
-                      template-haskell >= 2.15.0 && < 2.18
-
+                      template-haskell
 
   other-modules:      System.Console.Docopt
                       System.Console.Docopt.ApplicativeParsec
diff --git a/test/LangAgnosticTests.hs b/test/LangAgnosticTests.hs
--- a/test/LangAgnosticTests.hs
+++ b/test/LangAgnosticTests.hs
@@ -1,5 +1,8 @@
 {-# LANGUAGE FlexibleInstances #-}
 
+-- TODO: Remove orphan instances?
+{-# OPTIONS_GHC -Wno-orphans #-}
+
 import Control.Monad ( (>=>) )
 import System.Exit
 import System.Console.ANSI
@@ -104,18 +107,20 @@
                         -> ((Int, Int) -> Bool)
                         -> IO [Test]
 testsFromDocoptSpecFile name testFile ignore =
-  let notCommentLine x = null x || ('#' /= head x)
+  let notCommentLine x = case x of {[] -> True; (c:_) -> '#' /= c}
       testFileClean = unlines $ filter notCommentLine $ lines testFile
       caseGroups = filter (not . null) $ splitOn "r\"\"\"" testFileClean
 
   in
   return . (:[]) . TestLabel name . test $ zip caseGroups [(1 :: Int)..] >>= \(caseGroup, icg) -> do
 
-    let [usage, rawCases] = splitOn "\"\"\"" caseGroup
+    let (usage, rawCases) = case splitOn "\"\"\"" caseGroup of
+          [u, r] -> (u, r)
+          _ -> error $ "Unexpected format of 'caseGroup': " ++ caseGroup
         cases = filter (/= "\n") $ splitOn "$ " rawCases
 
     let (optFormat, docParseMsg) = case runParser pDocopt M.empty "Usage" usage of
-          Left e -> ((Sequence [], M.empty), "Couldn't parse usage text")
+          Left _e -> ((Sequence [], M.empty), "Couldn't parse usage text")
           Right o -> (o, "")
 
     let groupDescLines = [
@@ -131,9 +136,9 @@
       let (cmdline, rawTarget_) = break (== '\n') testcase
           rawTarget = filter (/= '\n') rawTarget_
           maybeTargetJSON = decode (BS.pack rawTarget) :: Maybe Value
-          rawArgs = tail $ words cmdline
+          rawArgs = drop 1 (words cmdline)
 
-      let (parsedArgs, argParseMsg) = case getArguments optFormat rawArgs of
+      let (parsedArgs, _argParseMsg) = case getArguments optFormat rawArgs of
             Left e -> (M.empty, "Parse Error: " ++ red (show e) ++ "\n")
             Right a -> (a, "")
 
