diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## v0.2.1.0
+
+* Drop support for GHC < 9.0
+
 ## v0.2.0.0
 
 * Add getFieldOr [#10](https://github.com/brandonchinn178/toml-reader/issues/10)
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # toml-reader
 
-[![](https://img.shields.io/github/workflow/status/brandonchinn178/toml-reader/CI/main)](https://github.com/brandonchinn178/toml-reader/actions)
+[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/brandonchinn178/toml-reader/ci.yml?branch=main)](https://github.com/brandonchinn178/toml-reader/actions?query=branch%3Amain)
 [![](https://img.shields.io/codecov/c/gh/brandonchinn178/toml-reader)](https://app.codecov.io/gh/brandonchinn178/toml-reader)
 [![](https://img.shields.io/hackage/v/toml-reader)](https://hackage.haskell.org/package/toml-reader)
 
diff --git a/src/TOML/Decode.hs b/src/TOML/Decode.hs
--- a/src/TOML/Decode.hs
+++ b/src/TOML/Decode.hs
@@ -92,32 +92,31 @@
 
 {--- Decoder ---}
 
-{- |
-A @Decoder a@ represents a function for decoding a TOML value to a value of type @a@.
-
-Generally, you'd only need to chain the @getField*@ functions together, like
-
-@
-decoder =
-  MyConfig
-    \<$> getField "a"
-    \<*> getField "b"
-    \<*> getField "c"
-@
-
-or use interfaces like 'Monad' and 'Alternative':
-
-@
-decoder = do
-  cfgType <- getField "type"
-  case cfgType of
-    "int" -> MyIntValue \<$> (getField "int" \<|> getField "integer")
-    "bool" -> MyBoolValue \<$> getField "bool"
-    _ -> fail $ "Invalid type: " <> cfgType
-@
-
-but you can also manually implement a 'Decoder' with 'makeDecoder'.
--}
+-- |
+-- A @Decoder a@ represents a function for decoding a TOML value to a value of type @a@.
+--
+-- Generally, you'd only need to chain the @getField*@ functions together, like
+--
+-- @
+-- decoder =
+--   MyConfig
+--     \<$> getField "a"
+--     \<*> getField "b"
+--     \<*> getField "c"
+-- @
+--
+-- or use interfaces like 'Monad' and 'Alternative':
+--
+-- @
+-- decoder = do
+--   cfgType <- getField "type"
+--   case cfgType of
+--     "int" -> MyIntValue \<$> (getField "int" \<|> getField "integer")
+--     "bool" -> MyBoolValue \<$> getField "bool"
+--     _ -> fail $ "Invalid type: " <> cfgType
+-- @
+--
+-- but you can also manually implement a 'Decoder' with 'makeDecoder'.
 newtype Decoder a = Decoder {unDecoder :: Value -> DecodeM a}
 
 instance Functor Decoder where
@@ -181,54 +180,51 @@
   fail = decodeFail . Text.pack
 #endif
 
-{- |
-Run a 'Decoder' with the given 'Value'.
-
-@
-makeDecoder $ \\v -> do
-  a <- runDecoder decoder1 v
-  b <- runDecoder decoder2 v
-  return (a, b)
-@
-
-Satisfies
-
-@
-makeDecoder . runDecoder === id
-runDecoder . makeDecoder === id
-@
--}
+-- |
+-- Run a 'Decoder' with the given 'Value'.
+--
+-- @
+-- makeDecoder $ \\v -> do
+--   a <- runDecoder decoder1 v
+--   b <- runDecoder decoder2 v
+--   return (a, b)
+-- @
+--
+-- Satisfies
+--
+-- @
+-- makeDecoder . runDecoder === id
+-- runDecoder . makeDecoder === id
+-- @
 runDecoder :: Decoder a -> Value -> DecodeM a
 runDecoder decoder v = DecodeM (decoderToEither decoder v)
 
-{- |
-Throw an error indicating that the given 'Value' is invalid.
-
-@
-makeDecoder $ \\v ->
-  case v of
-    Integer 42 -> invalidValue "We don't like this number" v
-    _ -> runDecoder tomlDecoder v
-
--- or alternatively,
-tomlDecoder >>= \case
-  42 -> makeDecoder $ invalidValue "We don't like this number"
-  v -> pure v
-@
--}
+-- |
+-- Throw an error indicating that the given 'Value' is invalid.
+--
+-- @
+-- makeDecoder $ \\v ->
+--   case v of
+--     Integer 42 -> invalidValue "We don't like this number" v
+--     _ -> runDecoder tomlDecoder v
+--
+-- -- or alternatively,
+-- tomlDecoder >>= \case
+--   42 -> makeDecoder $ invalidValue "We don't like this number"
+--   v -> pure v
+-- @
 invalidValue :: Text -> Value -> DecodeM a
 invalidValue msg v = decodeError $ InvalidValue msg v
 
-{- |
-Throw an error indicating that the given 'Value' isn't the correct type of value.
-
-@
-makeDecoder $ \\v ->
-  case v of
-    String s -> ...
-    _ -> typeMismatch v
-@
--}
+-- |
+-- Throw an error indicating that the given 'Value' isn't the correct type of value.
+--
+-- @
+-- makeDecoder $ \\v ->
+--   case v of
+--     String s -> ...
+--     _ -> typeMismatch v
+-- @
 typeMismatch :: Value -> DecodeM a
 typeMismatch v = decodeError $ TypeMismatch v
 
@@ -246,7 +242,7 @@
 {--- Decoding ---}
 
 -- | Decode the given TOML input.
-decode :: DecodeTOML a => Text -> Either TOMLError a
+decode :: (DecodeTOML a) => Text -> Either TOMLError a
 decode = decodeWith tomlDecoder
 
 -- | Decode the given TOML input using the given 'Decoder'.
@@ -259,81 +255,77 @@
   first (uncurry DecodeError) $ decoderToEither decoder v []
 
 -- | Decode a TOML file at the given file path.
-decodeFile :: DecodeTOML a => FilePath -> IO (Either TOMLError a)
+decodeFile :: (DecodeTOML a) => FilePath -> IO (Either TOMLError a)
 decodeFile fp = decodeWithOpts tomlDecoder fp <$> Text.readFile fp
 
 {--- Decoder helpers ---}
 
-{- |
-Decode a field in a TOML Value.
-Equivalent to 'getFields' with a single-element list.
-
-@
-a = 1
-b = 'asdf'
-@
-
-@
--- MyConfig 1 "asdf"
-MyConfig \<$> getField "a" \<*> getField "b"
-@
--}
-getField :: DecodeTOML a => Text -> Decoder a
+-- |
+-- Decode a field in a TOML Value.
+-- Equivalent to 'getFields' with a single-element list.
+--
+-- @
+-- a = 1
+-- b = 'asdf'
+-- @
+--
+-- @
+-- -- MyConfig 1 "asdf"
+-- MyConfig \<$> getField "a" \<*> getField "b"
+-- @
+getField :: (DecodeTOML a) => Text -> Decoder a
 getField = getFieldWith tomlDecoder
 
-{- |
-Decode a field in a TOML Value or succeed with a default value when the field is missing.
-
-@
-a = 1
-# b is missing
-@
-
-@
--- MyConfig 1 "asdf"
-MyConfig \<$> getFieldOr 42 "a" \<*> getFieldOr "asdf" "b"
-@
--}
-getFieldOr :: DecodeTOML a => a -> Text -> Decoder a
+-- |
+-- Decode a field in a TOML Value or succeed with a default value when the field is missing.
+--
+-- @
+-- a = 1
+-- # b is missing
+-- @
+--
+-- @
+-- -- MyConfig 1 "asdf"
+-- MyConfig \<$> getFieldOr 42 "a" \<*> getFieldOr "asdf" "b"
+-- @
+getFieldOr :: (DecodeTOML a) => a -> Text -> Decoder a
 getFieldOr def key = fromMaybe def <$> getFieldOpt key
 
 -- | Same as 'getField', except with the given 'Decoder'.
 getFieldWith :: Decoder a -> Text -> Decoder a
 getFieldWith decoder key = getFieldsWith decoder [key]
 
-{- |
-Decode a field in a TOML Value, or Nothing if the field doesn't exist.
-Equivalent to 'getFieldsOpt' with a single-element list.
-
-@
-a = 1
-@
-
-@
--- MyConfig (Just 1) Nothing
-MyConfig \<$> getFieldOpt "a" \<*> getFieldOpt "b"
-@
--}
-getFieldOpt :: DecodeTOML a => Text -> Decoder (Maybe a)
+-- |
+-- Decode a field in a TOML Value, or Nothing if the field doesn't exist.
+-- Equivalent to 'getFieldsOpt' with a single-element list.
+--
+-- @
+-- a = 1
+-- @
+--
+-- @
+-- -- MyConfig (Just 1) Nothing
+-- MyConfig \<$> getFieldOpt "a" \<*> getFieldOpt "b"
+-- @
+getFieldOpt :: (DecodeTOML a) => Text -> Decoder (Maybe a)
 getFieldOpt = getFieldOptWith tomlDecoder
 
 -- | Same as 'getFieldOpt', except with the given 'Decoder'.
 getFieldOptWith :: Decoder a -> Text -> Decoder (Maybe a)
 getFieldOptWith decoder key = getFieldsOptWith decoder [key]
 
-{- |
-Decode a nested field in a TOML Value.
-
-@
-a.b = 1
-@
-
-@
--- MyConfig 1
-MyConfig \<$> getFields ["a", "b"]
-@
--}
-getFields :: DecodeTOML a => [Text] -> Decoder a
+-- |
+-- Decode a nested field in a TOML Value.
+--
+-- @
+-- a.b = 1
+-- @
+--
+-- @
+-- -- MyConfig 1
+-- MyConfig \<$> getFields ["a", "b"]
+-- @
+getFields :: (DecodeTOML a) => [Text] -> Decoder a
 getFields = getFieldsWith tomlDecoder
 
 -- | Same as 'getFields', except with the given 'Decoder'.
@@ -350,22 +342,21 @@
               Nothing -> decodeError MissingField
         _ -> typeMismatch v
 
-{- |
-Decode a nested field in a TOML Value, or 'Nothing' if any of the fields don't exist.
-
-@
-a.b = 1
-@
-
-@
--- MyConfig (Just 1) Nothing Nothing
-MyConfig
-  \<$> getFieldsOpt ["a", "b"]
-  \<*> getFieldsOpt ["a", "c"]
-  \<*> getFieldsOpt ["b", "c"]
-@
--}
-getFieldsOpt :: DecodeTOML a => [Text] -> Decoder (Maybe a)
+-- |
+-- Decode a nested field in a TOML Value, or 'Nothing' if any of the fields don't exist.
+--
+-- @
+-- a.b = 1
+-- @
+--
+-- @
+-- -- MyConfig (Just 1) Nothing Nothing
+-- MyConfig
+--   \<$> getFieldsOpt ["a", "b"]
+--   \<*> getFieldsOpt ["a", "c"]
+--   \<*> getFieldsOpt ["b", "c"]
+-- @
+getFieldsOpt :: (DecodeTOML a) => [Text] -> Decoder (Maybe a)
 getFieldsOpt = getFieldsOptWith tomlDecoder
 
 -- | Same as 'getFieldsOpt', except with the given 'Decoder'.
@@ -378,23 +369,22 @@
         Left (ctx', e) -> Left (ctx', e)
         Right x -> Right $ Just x
 
-{- |
-Decode a list of values using the given 'Decoder'.
-
-@
-[[a]]
-b = 1
-
-[[a]]
-b = 2
-@
-
-@
--- MyConfig [1, 2]
-MyConfig
-  \<$> getFieldWith (getArrayOf (getField "b")) "a"
-@
--}
+-- |
+-- Decode a list of values using the given 'Decoder'.
+--
+-- @
+-- [[a]]
+-- b = 1
+--
+-- [[a]]
+-- b = 2
+-- @
+--
+-- @
+-- -- MyConfig [1, 2]
+-- MyConfig
+--   \<$> getFieldWith (getArrayOf (getField "b")) "a"
+-- @
 getArrayOf :: Decoder a -> Decoder [a]
 getArrayOf decoder =
   makeDecoder $ \case
@@ -403,11 +393,10 @@
 
 {--- DecodeTOML ---}
 
-{- |
-A type class containing the default 'Decoder' for the given type.
-
-See the docs for 'Decoder' for examples.
--}
+-- |
+-- A type class containing the default 'Decoder' for the given type.
+--
+-- See the docs for 'Decoder' for examples.
 class DecodeTOML a where
   tomlDecoder :: Decoder a
 
@@ -428,7 +417,7 @@
       Integer x -> pure x
       v -> typeMismatch v
 
-tomlDecoderInt :: forall a. Num a => Decoder a
+tomlDecoderInt :: forall a. (Num a) => Decoder a
 tomlDecoderInt = fromInteger <$> tomlDecoder
 
 tomlDecoderBoundedInt :: forall a. (Integral a, Bounded a) => Decoder a
@@ -472,14 +461,14 @@
       Float x -> pure x
       v -> typeMismatch v
 
-tomlDecoderFrac :: Fractional a => Decoder a
+tomlDecoderFrac :: (Fractional a) => Decoder a
 tomlDecoderFrac = realToFrac <$> tomlDecoder @Double
 
 instance DecodeTOML Float where
   tomlDecoder = tomlDecoderFrac
-instance Integral a => DecodeTOML (Ratio a) where
+instance (Integral a) => DecodeTOML (Ratio a) where
   tomlDecoder = tomlDecoderFrac
-instance HasResolution a => DecodeTOML (Fixed a) where
+instance (HasResolution a) => DecodeTOML (Fixed a) where
   tomlDecoder = tomlDecoderFrac
 
 instance DecodeTOML Char where
@@ -568,46 +557,45 @@
       "GT" -> pure GT
       _ -> makeDecoder $ invalidValue "Invalid Ordering"
 
-instance DecodeTOML a => DecodeTOML (Identity a) where
+instance (DecodeTOML a) => DecodeTOML (Identity a) where
   tomlDecoder = Identity <$> tomlDecoder
 instance DecodeTOML (Proxy a) where
   tomlDecoder = pure Proxy
-instance DecodeTOML a => DecodeTOML (Const a b) where
+instance (DecodeTOML a) => DecodeTOML (Const a b) where
   tomlDecoder = Const <$> tomlDecoder
 
-{- |
-Since TOML doesn't support literal NULLs, this will only ever return 'Just'.
-To get the absence of a field, use 'getFieldOpt' or one of its variants.
--}
-instance DecodeTOML a => DecodeTOML (Maybe a) where
+-- |
+-- Since TOML doesn't support literal NULLs, this will only ever return 'Just'.
+-- To get the absence of a field, use 'getFieldOpt' or one of its variants.
+instance (DecodeTOML a) => DecodeTOML (Maybe a) where
   tomlDecoder = Just <$> tomlDecoder
 
 instance (DecodeTOML a, DecodeTOML b) => DecodeTOML (Either a b) where
   tomlDecoder = (Right <$> tomlDecoder) <|> (Left <$> tomlDecoder)
 
-instance DecodeTOML a => DecodeTOML (Monoid.First a) where
+instance (DecodeTOML a) => DecodeTOML (Monoid.First a) where
   tomlDecoder = Monoid.First <$> tomlDecoder
-instance DecodeTOML a => DecodeTOML (Monoid.Last a) where
+instance (DecodeTOML a) => DecodeTOML (Monoid.Last a) where
   tomlDecoder = Monoid.Last <$> tomlDecoder
-instance DecodeTOML a => DecodeTOML (Semigroup.First a) where
+instance (DecodeTOML a) => DecodeTOML (Semigroup.First a) where
   tomlDecoder = Semigroup.First <$> tomlDecoder
-instance DecodeTOML a => DecodeTOML (Semigroup.Last a) where
+instance (DecodeTOML a) => DecodeTOML (Semigroup.Last a) where
   tomlDecoder = Semigroup.Last <$> tomlDecoder
-instance DecodeTOML a => DecodeTOML (Semigroup.Max a) where
+instance (DecodeTOML a) => DecodeTOML (Semigroup.Max a) where
   tomlDecoder = Semigroup.Max <$> tomlDecoder
-instance DecodeTOML a => DecodeTOML (Semigroup.Min a) where
+instance (DecodeTOML a) => DecodeTOML (Semigroup.Min a) where
   tomlDecoder = Semigroup.Min <$> tomlDecoder
-instance DecodeTOML a => DecodeTOML (Monoid.Dual a) where
+instance (DecodeTOML a) => DecodeTOML (Monoid.Dual a) where
   tomlDecoder = Monoid.Dual <$> tomlDecoder
 
-instance DecodeTOML a => DecodeTOML [a] where
+instance (DecodeTOML a) => DecodeTOML [a] where
   tomlDecoder = getArrayOf tomlDecoder
 instance (IsString k, Ord k, DecodeTOML v) => DecodeTOML (Map k v) where
   tomlDecoder =
     makeDecoder $ \case
       Table o -> Map.mapKeys (fromString . Text.unpack) <$> mapM (runDecoder tomlDecoder) o
       v -> typeMismatch v
-instance DecodeTOML a => DecodeTOML (NonEmpty a) where
+instance (DecodeTOML a) => DecodeTOML (NonEmpty a) where
   tomlDecoder = maybe raiseEmpty pure . NonEmpty.nonEmpty =<< tomlDecoder
     where
       raiseEmpty = makeDecoder $ invalidValue "Got empty list"
@@ -615,9 +603,9 @@
   tomlDecoder = IntSet.fromList <$> tomlDecoder
 instance (DecodeTOML a, Ord a) => DecodeTOML (Set a) where
   tomlDecoder = Set.fromList <$> tomlDecoder
-instance DecodeTOML a => DecodeTOML (IntMap a) where
+instance (DecodeTOML a) => DecodeTOML (IntMap a) where
   tomlDecoder = IntMap.fromList <$> tomlDecoder
-instance DecodeTOML a => DecodeTOML (Seq a) where
+instance (DecodeTOML a) => DecodeTOML (Seq a) where
   tomlDecoder = Seq.fromList <$> tomlDecoder
 
 tomlDecoderTuple :: ([Value] -> Maybe (DecodeM a)) -> Decoder a
@@ -625,7 +613,7 @@
   makeDecoder $ \case
     Array vs | Just decodeM <- f vs -> decodeM
     v -> typeMismatch v
-decodeElem :: DecodeTOML a => Int -> Value -> DecodeM a
+decodeElem :: (DecodeTOML a) => Int -> Value -> DecodeM a
 decodeElem i v = addContextItem (Index i) (runDecoder tomlDecoder v)
 instance DecodeTOML () where
   tomlDecoder = tomlDecoderTuple $ \case
diff --git a/src/TOML/Parser.hs b/src/TOML/Parser.hs
--- a/src/TOML/Parser.hs
+++ b/src/TOML/Parser.hs
@@ -5,7 +5,7 @@
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE TypeFamilies #-}
 
-{- |
+{-|
 Parse a TOML document.
 
 References:
@@ -44,11 +44,11 @@
 import TOML.Value (Table, Value (..))
 
 parseTOML ::
-  -- | Name of file (for error messages)
-  String ->
-  -- | Input
-  Text ->
-  Either TOMLError Value
+  String
+  -- ^ Name of file (for error messages)
+  -> Text
+  -- ^ Input
+  -> Either TOMLError Value
 parseTOML filename input =
   case runParser parseTOMLDocument filename input of
     Left e -> Left $ ParseError $ Text.pack $ errorBundlePretty e
@@ -68,9 +68,9 @@
   | GenericLocalTime TimeOfDay
 
 fromGenericValue ::
-  (map key (GenericValue map key tableMeta arrayMeta) -> Table) ->
-  GenericValue map key tableMeta arrayMeta ->
-  Value
+  (map key (GenericValue map key tableMeta arrayMeta) -> Table)
+  -> GenericValue map key tableMeta arrayMeta
+  -> Value
 fromGenericValue fromGenericTable = \case
   GenericTable _ t -> Table $ fromGenericTable t
   GenericArray _ vs -> Array $ map (fromGenericValue fromGenericTable) vs
@@ -261,13 +261,12 @@
       guard $ isUnicodeScalar code
       pure $ chr code
 
-{- |
-Parse the multiline delimiter (" in """ quotes, or ' in ''' quotes), unless
-the delimiter indicates the end of the multiline string.
-
-i.e. parse 1 or 2 delimiters, or 4 or 5, which is 1 or 2 delimiters at the
-end of a multiline string (then backtrack 3 to mark the end).
--}
+-- |
+-- Parse the multiline delimiter (" in """ quotes, or ' in ''' quotes), unless
+-- the delimiter indicates the end of the multiline string.
+--
+-- i.e. parse 1 or 2 delimiters, or 4 or 5, which is 1 or 2 delimiters at the
+-- end of a multiline string (then backtrack 3 to mark the end).
 parseMultilineDelimiter :: Char -> Parser Text
 parseMultilineDelimiter delim =
   choice
@@ -687,11 +686,11 @@
     }
 
 setValueAtPath ::
-  ValueAtPathOptions ->
-  Key ->
-  AnnTable ->
-  (Maybe AnnValue -> NormalizeM AnnValue) ->
-  NormalizeM AnnTable
+  ValueAtPathOptions
+  -> Key
+  -> AnnTable
+  -> (Maybe AnnValue -> NormalizeM AnnValue)
+  -> NormalizeM AnnTable
 setValueAtPath ValueAtPathOptions{..} fullKey initialTable f = do
   (mValue, setValue) <- getPathLens doRecurse fullKey initialTable
   setValue <$> f mValue
@@ -752,7 +751,7 @@
 parseSignRaw :: Parser Text
 parseSignRaw = optionalOr "" (string "-" <|> string "+")
 
-parseSign :: Num a => Parser (a -> a)
+parseSign :: (Num a) => Parser (a -> a)
 parseSign = do
   sign <- parseSignRaw
   pure $ if sign == "-" then negate else id
@@ -853,7 +852,7 @@
             | otherwise = error $ "readBin got unexpected digit: " <> show x
        in 2 * acc + digit
 
-runReader :: Show a => ReadS a -> Text -> a
+runReader :: (Show a) => ReadS a -> Text -> a
 runReader rdr digits =
   case rdr $ Text.unpack digits of
     [(x, "")] -> x
diff --git a/src/TOML/Utils/Map.hs b/src/TOML/Utils/Map.hs
--- a/src/TOML/Utils/Map.hs
+++ b/src/TOML/Utils/Map.hs
@@ -12,27 +12,26 @@
 
 import TOML.Utils.NonEmpty (zipHistory)
 
-{- |
-For a non-empty list of keys, iterate through the given 'Map' and return
-the possibly missing value at the path and a function to set the value at
-the given path and return the modified input 'Map'.
-
-@
-let obj = undefined -- { "a": { "b": { "c": 1 } } }
-(mValue, setValue) <- getPathLens doRecurse ["a", "b", "c"] obj
-
-print mValue -- Just 1
-print (setValue 2) -- { "a": { "b": { "c": 2 } } }
-@
--}
+-- |
+-- For a non-empty list of keys, iterate through the given 'Map' and return
+-- the possibly missing value at the path and a function to set the value at
+-- the given path and return the modified input 'Map'.
+--
+-- @
+-- let obj = undefined -- { "a": { "b": { "c": 1 } } }
+-- (mValue, setValue) <- getPathLens doRecurse ["a", "b", "c"] obj
+--
+-- print mValue -- Just 1
+-- print (setValue 2) -- { "a": { "b": { "c": 2 } } }
+-- @
 getPathLens ::
   (Monad m, Ord k) =>
-  -- | How to get and set the next Map from the possibly missing value.
+  (NonEmpty k -> Maybe v -> m (Map k v, Map k v -> v))
+  -- ^ How to get and set the next Map from the possibly missing value.
   -- Passes in the path taken so far.
-  (NonEmpty k -> Maybe v -> m (Map k v, Map k v -> v)) ->
-  NonEmpty k ->
-  Map k v ->
-  m (Maybe v, v -> Map k v)
+  -> NonEmpty k
+  -> Map k v
+  -> m (Maybe v, v -> Map k v)
 getPathLens =
   getPathLensWith (\setVal fromMap -> mkSetter (setVal . fromMap)) (mkSetter id)
   where
@@ -41,10 +40,10 @@
 -- | Same as 'getPathLens', except without the setter.
 getPath ::
   (Monad m, Ord k) =>
-  (NonEmpty k -> Maybe v -> m (Map k v)) ->
-  NonEmpty k ->
-  Map k v ->
-  m (Maybe v)
+  (NonEmpty k -> Maybe v -> m (Map k v))
+  -> NonEmpty k
+  -> Map k v
+  -> m (Maybe v)
 getPath doRecurse path originalMap =
   fst <$> getPathLensWith (\_ _ _ _ -> ()) (\_ _ -> ()) doRecurse' path originalMap
   where
@@ -54,12 +53,12 @@
 
 getPathLensWith ::
   (Monad m, Ord k) =>
-  (b -> a -> (k -> Map k v -> b)) ->
-  (k -> Map k v -> b) ->
-  (NonEmpty k -> Maybe v -> m (Map k v, a)) ->
-  NonEmpty k ->
-  Map k v ->
-  m (Maybe v, b)
+  (b -> a -> (k -> Map k v -> b))
+  -> (k -> Map k v -> b)
+  -> (NonEmpty k -> Maybe v -> m (Map k v, a))
+  -> NonEmpty k
+  -> Map k v
+  -> m (Maybe v, b)
 getPathLensWith mkAnn mkFirstAnn doRecurse path originalMap =
   let (_, k) :| ks = zipHistory path
    in foldlM go (buildLens k mkFirstAnn originalMap) ks
diff --git a/src/TOML/Utils/NonEmpty.hs b/src/TOML/Utils/NonEmpty.hs
--- a/src/TOML/Utils/NonEmpty.hs
+++ b/src/TOML/Utils/NonEmpty.hs
@@ -8,12 +8,11 @@
 import Data.List.NonEmpty (NonEmpty ((:|)))
 import qualified Data.List.NonEmpty as NonEmpty
 
-{- |
-Annotates each element with the history of all past elements.
-
->>> zipHistory ["a", "b", "c"]
-[(["a"], "a"), (["a", "b"], "b"), (["a", "b", "c"], "c")]
--}
+-- |
+-- Annotates each element with the history of all past elements.
+--
+-- >>> zipHistory ["a", "b", "c"]
+-- [(["a"], "a"), (["a", "b"], "b"), (["a", "b", "c"], "c")]
 zipHistory :: NonEmpty a -> NonEmpty (NonEmpty a, a)
 zipHistory (a :| as) =
   NonEmpty.fromList $
diff --git a/src/TOML/Value.hs b/src/TOML/Value.hs
--- a/src/TOML/Value.hs
+++ b/src/TOML/Value.hs
@@ -44,5 +44,5 @@
   where
     renderKeyValue (k, v) = showT k <> ": " <> renderValue v
 
-    showT :: Show a => a -> Text
+    showT :: (Show a) => a -> Text
     showT = Text.pack . show
diff --git a/test/tasty/TOML/Utils/MapTest.hs b/test/tasty/TOML/Utils/MapTest.hs
--- a/test/tasty/TOML/Utils/MapTest.hs
+++ b/test/tasty/TOML/Utils/MapTest.hs
@@ -23,9 +23,9 @@
   deriving (Show, Eq)
 
 recurseMapOrInt ::
-  NonEmpty String ->
-  Maybe MapOrInt ->
-  Either String (Map String MapOrInt, Map String MapOrInt -> MapOrInt)
+  NonEmpty String
+  -> Maybe MapOrInt
+  -> Either String (Map String MapOrInt, Map String MapOrInt -> MapOrInt)
 recurseMapOrInt _ = \case
   Nothing -> Right (Map.empty, fromMap)
   Just (Map kvs) -> Right (Map.fromList kvs, fromMap)
diff --git a/test/toml-test/ValidateParser.hs b/test/toml-test/ValidateParser.hs
--- a/test/toml-test/ValidateParser.hs
+++ b/test/toml-test/ValidateParser.hs
@@ -25,6 +25,7 @@
 import qualified Data.Aeson.Key as Key
 import Data.Aeson.KeyMap (KeyMap)
 import qualified Data.Aeson.KeyMap as KeyMap
+import Data.HashMap.Lazy ()
 #else
 import qualified Data.HashMap.Lazy as HashMap
 #endif
diff --git a/toml-reader.cabal b/toml-reader.cabal
--- a/toml-reader.cabal
+++ b/toml-reader.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.35.0.
+-- This file has been generated from package.yaml by hpack version 0.35.2.
 --
 -- see: https://github.com/sol/hpack
 
 name:           toml-reader
-version:        0.2.0.0
+version:        0.2.1.0
 synopsis:       TOML format parser compliant with v1.0.0.
 description:    TOML format parser compliant with v1.0.0. See README.md for more details.
 category:       TOML, Text, Configuration
@@ -49,17 +49,15 @@
       Paths_toml_reader
   hs-source-dirs:
       src
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances -Wunused-packages
   build-depends:
-      base >=4.9 && <5
-    , containers >=0.6.0.1 && <0.7
-    , megaparsec >=7.0.5 && <9.3
-    , parser-combinators >=1.1.0 && <1.4
-    , text >=1.2.3.1 && <2.1
-    , time >=1.8.0.2 && <1.13
+      base >=4.15 && <5
+    , containers <0.7
+    , megaparsec <9.5
+    , parser-combinators <1.4
+    , text <2.1
+    , time <1.13
   default-language: Haskell2010
-  if impl(ghc >= 8.0)
-    ghc-options: -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
 
 test-suite parser-validator
   type: exitcode-stdio-1.0
@@ -68,7 +66,7 @@
       Paths_toml_reader
   hs-source-dirs:
       test/toml-test
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances -Wunused-packages
   build-depends:
       aeson
     , base
@@ -82,8 +80,6 @@
     , unordered-containers
     , vector
   default-language: Haskell2010
-  if impl(ghc >= 8.0)
-    ghc-options: -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
 
 test-suite toml-reader-tests
   type: exitcode-stdio-1.0
@@ -97,7 +93,7 @@
       Paths_toml_reader
   hs-source-dirs:
       test/tasty
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances -Wunused-packages
   build-depends:
       base
     , containers
@@ -108,5 +104,3 @@
     , time
     , toml-reader
   default-language: Haskell2010
-  if impl(ghc >= 8.0)
-    ghc-options: -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
