diff --git a/CHANGES.markdown b/CHANGES.markdown
--- a/CHANGES.markdown
+++ b/CHANGES.markdown
@@ -1,3 +1,6 @@
+Changes in 0.20.1
+  - GHC 9.4 compatibility. (#382)
+
 Changes in 0.20.0
   - Allow doctest to be invoked via `cabal repl --with-ghc=doctest`
   - Include `ghc --info` output in `--info`
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009-2018 Simon Hengel <sol@typeful.net>
+Copyright (c) 2009-2022 Simon Hengel <sol@typeful.net>
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/README.markdown b/README.markdown
deleted file mode 100644
--- a/README.markdown
+++ /dev/null
@@ -1,479 +0,0 @@
-# Doctest: Test interactive Haskell examples
-
-`doctest` is a small program, that checks [examples in Haddock comments](http://www.haskell.org/haddock/doc/html/ch03s08.html#id566093).  It is similar
-to the [popular Python module with the same name](http://docs.python.org/library/doctest.html).
-
-
-## Installation
-
-`doctest` is available from
-[Hackage](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/doctest).
-Install it, by typing:
-
-    cabal install doctest
-
-Make sure that Cabal's `bindir` is on your `PATH`.
-
-On Linux:
-
-    export PATH="$HOME/.cabal/bin:$PATH"
-
-On Mac OS X:
-
-    export PATH="$HOME/Library/Haskell/bin:$PATH"
-
-On Windows:
-
-    set PATH="%AppData%\cabal\bin\;%PATH%"
-
-For more information, see the [section on paths in the Cabal User Guide](http://www.haskell.org/cabal/users-guide/installing-packages.html#paths-in-the-simple-build-system).
-
-## Usage
-
-Below is a small Haskell module.
-The module contains a Haddock comment with some examples of interaction.
-The examples demonstrate how the module is supposed to be used.
-
-```haskell
-module Fib where
-
--- | Compute Fibonacci numbers
---
--- Examples:
---
--- >>> fib 10
--- 55
---
--- >>> fib 5
--- 5
-fib :: Int -> Int
-fib 0 = 0
-fib 1 = 1
-fib n = fib (n - 1) + fib (n - 2)
-```
-
-(A comment line starting with `>>>` denotes an _expression_.
-All comment lines following an expression denote the _result_ of that expression.
-Result is defined by what a
-[REPL](http://en.wikipedia.org/wiki/Read-eval-print_loop) (e.g. ghci)
-prints to `stdout` and `stderr` when evaluating that expression.)
-
-With `doctest` you may check whether the implementation satisfies the given examples, by typing:
-
-    doctest Fib.hs
-
-You may produce Haddock documentation for that module with:
-
-    haddock -h Fib.hs -o doc/
-
-`doctest` will fail on comments that `haddock` also doesn't like.
-Sometimes (e.g., [#251](https://github.com/sol/doctest/issues/251)), this means that `doctest` will fail on input that GHC accepts.
-
-`doctest` likes UTF-8. If you are running it with, e.g., `LC_ALL=C`,
-you may need to invoke `doctest` with `LC_ALL=C.UTF-8`.
-
-### Example groups
-
-Examples from a single Haddock comment are grouped together and share the same
-scope.  E.g. the following works:
-
-```haskell
--- |
--- >>> let x = 23
--- >>> x + 42
--- 65
-```
-
-If an example fails, subsequent examples from the same group are skipped.  E.g.
-for
-
-```haskell
--- |
--- >>> let x = 23
--- >>> let n = x + y
--- >>> print n
-```
-
-`print n` is not tried, because `let n = x + y` fails (`y` is not in scope!).
-
-#### A note on performance
-
-By default, `doctest` calls `:reload` between each group to clear GHCi's scope
-of any local definitions. This ensures that previous examples cannot influence
-later ones. However, it can lead to performance penalties if you are using
-`doctest` in a project with many modules. One possible remedy is to pass the
-`--fast` flag to `doctest`, which disables calling `:reload` between groups.
-If `doctest`s are running too slowly, you might consider using `--fast`.
-(With the caveat that the order in which groups appear now matters!)
-
-However, note that due to a
-[bug on GHC 8.2.1 or later](https://ghc.haskell.org/trac/ghc/ticket/14052),
-the performance of `--fast` suffers significantly when combined with the
-`--preserve-it` flag (which keeps the value of GHCi's `it` value between
-examples).
-
-### Setup code
-
-You can put setup code in a [named chunk][named-chunks] with the name `$setup`.
-The setup code is run before each example group.  If the setup code produces
-any errors/failures, all tests from that module are skipped.
-
-Here is an example:
-
-```haskell
-module Foo where
-
-import Bar.Baz
-
--- $setup
--- >>> let x = 23 :: Int
-
--- |
--- >>> foo + x
--- 65
-foo :: Int
-foo = 42
-```
-
-Note that you should not place setup code inbetween the module header (`module
-...  where`) and import declarations. GHC will not be able to parse it ([issue
- #167](https://github.com/sol/doctest/issues/167)). It is best to place setup
-code right after import declarations, but due to its declarative nature you can
-place it anywhere inbetween top level declarations as well.
-
-
-### Multi-line input
-GHCi supports commands which span multiple lines, and the same syntax works for doctest:
-
-```haskell
--- |
--- >>> :{
---  let
---    x = 1
---    y = 2
---  in x + y + multiline
--- :}
--- 6
-multiline = 3
-```
-
-Note that `>>>` can be left off for the lines following the first: this is so that
-haddock does not strip leading whitespace. The expected output has whitespace
-stripped relative to the :}.
-
-Some peculiarities on the ghci side mean that whitespace at the very start is lost.
-This breaks the example `broken`, since the x and y aren't aligned from ghci's
-perspective.  A workaround is to avoid leading space, or add a newline such
-that the indentation does not matter:
-
-```haskell
-{- | >>> :{
-let x = 1
-    y = 2
-  in x + y + works
-:}
-6
--}
-works = 3
-
-{- | >>> :{
- let x = 1
-     y = 2
-  in x + y + broken
-:}
-3
--}
-broken = 3
-```
-
-### Multi-line output
-If there are no blank lines in the output, multiple lines are handled
-automatically.
-
-```haskell
--- | >>> putStr "Hello\nWorld!"
--- Hello
--- World!
-```
-
-If however the output contains blank lines, they must be noted
-explicitly with `<BLANKLINE>`. For example,
-
-```haskell
-import Data.List ( intercalate )
-
--- | Double-space a paragraph.
---
---   Examples:
---
---   >>> let s1 = "\"Every one of whom?\""
---   >>> let s2 = "\"Every one of whom do you think?\""
---   >>> let s3 = "\"I haven't any idea.\""
---   >>> let paragraph = unlines [s1,s2,s3]
---   >>> putStrLn $ doubleSpace paragraph
---   "Every one of whom?"
---   <BLANKLINE>
---   "Every one of whom do you think?"
---   <BLANKLINE>
---   "I haven't any idea."
---
-doubleSpace :: String -> String
-doubleSpace = (intercalate "\n\n") . lines
-```
-
-### Matching arbitrary output
-Any lines containing only three dots (`...`) will match one or more lines with
-arbitrary content. For instance,
-
-```haskell
--- |
--- >>> putStrLn "foo\nbar\nbaz"
--- foo
--- ...
--- baz
-```
-
-If a line contains three dots and additional content, the three dots will match
-anything *within that line*:
-
-```haskell
--- |
--- >>> putStrLn "foo bar baz"
--- foo ... baz
-```
-
-### QuickCheck properties
-
-Haddock (since version 2.13.0) has markup support for properties.  Doctest can
-verify properties with QuickCheck.  A simple property looks like this:
-
-```haskell
--- |
--- prop> \xs -> sort xs == (sort . sort) (xs :: [Int])
-```
-
-The lambda abstraction is optional and can be omitted:
-
-```haskell
--- |
--- prop> sort xs == (sort . sort) (xs :: [Int])
-```
-
-A complete example that uses setup code is below:
-
-```haskell
-module Fib where
-
--- $setup
--- >>> import Control.Applicative
--- >>> import Test.QuickCheck
--- >>> newtype Small = Small Int deriving Show
--- >>> instance Arbitrary Small where arbitrary = Small . (`mod` 10) <$> arbitrary
-
--- | Compute Fibonacci numbers
---
--- The following property holds:
---
--- prop> \(Small n) -> fib n == fib (n + 2) - fib (n + 1)
-fib :: Int -> Int
-fib 0 = 0
-fib 1 = 1
-fib n = fib (n - 1) + fib (n - 2)
-```
-
-If you see an error like the following, ensure that
-[QuickCheck](http://hackage.haskell.org/package/QuickCheck) is a dependency
-of the test-suite or executable running `doctest`.
-
-```haskell
-<interactive>:39:3:
-    Not in scope: ‘polyQuickCheck’
-    In the splice: $(polyQuickCheck (mkName "doctest_prop"))
-
-<interactive>:39:3:
-    GHC stage restriction:
-      ‘polyQuickCheck’ is used in a top-level splice or annotation,
-      and must be imported, not defined locally
-    In the expression: polyQuickCheck (mkName "doctest_prop")
-    In the splice: $(polyQuickCheck (mkName "doctest_prop"))
-```
-
-### Hiding examples from Haddock
-
-You can put examples into [named chunks][named-chunks], and not refer to them
-in the export list.  That way they will not be part of the generated Haddock
-documentation, but Doctest will still find them.
-
-```haskell
--- $
--- >>> 1 + 1
--- 2
-```
-
-[named-chunks]: http://www.haskell.org/haddock/doc/html/ch03s05.html
-
-### Using GHC extensions
-
-There's two sets of GHC extensions involved when running Doctest:
-
-1. The set of GHC extensions that are active when compiling the module code
-(excluding the doctest examples). The easiest way to specify these extensions
-is through [LANGUAGE pragmas][language-pragma] in your source files.
-(Doctest will not look at your cabal file.)
-2. The set of GHC extensions that are active when executing the Doctest
-examples. (These are not influenced by the LANGUAGE pragmas in the file.) The
-recommended way to enable extensions for Doctest examples is to switch them
-on like this:
-
-```haskell
--- |
--- >>> :set -XTupleSections
--- >>> fst' $ (1,) 2
--- 1
-fst' :: (a, b) -> a
-fst' = fst
-```
-
-Alternatively you can pass any GHC options to Doctest, e.g.:
-
-    doctest -XCPP Foo.hs
-
-These options will affect both the loading of the module and the execution of
-the Doctest examples.
-
-If you want to omit the information which language extensions are enabled from
-the Doctest examples you can use the method described in [Hiding examples from
-Haddock](#hiding-examples-from-haddock), e.g.:
-
-```haskell
--- $
--- >>> :set -XTupleSections
-```
-
-[language-pragma]: http://www.haskell.org/ghc/docs/latest/html/users_guide/pragmas.html#language-pragma
-
-### Limitations
-
-Due to [a GHC bug](https://gitlab.haskell.org/ghc/ghc/-/issues/20670), running
-`:set -XTemplateHaskell` within `ghci` may unload any modules that were
-specified on the command line.
-
-To address this `doctest >= 0.19.0` does two things:
-
-1. Doctest always enables `-XTemplateHaskell`.  So it is safe to use Template
-   Haskell in examples without enabling the extension explicitly.
-1. Doctest filters out `-XTemplateHaskell` from single-line `:set`-statements.
-   So it is still safe to include `:set -XTemplateHaskell` in examples for
-   documentation purposes.  It may just not work as intended in `ghci` due to
-   that GHC bug.
-
-Doctest does not filter out `-XTemplateHaskell` from multi-line
-`:set`-statements.  So if you e.g. use
-
-```
->>> :{
-:set -XTemplateHaskell
-:}
-```
-then you are on your own.
-
-
-### Cabal integration
-
-Doctest provides both, an executable and a library.  The library exposes a
-function `doctest` of type:
-
-```haskell
-doctest :: [String] -> IO ()
-```
-
-Doctest's own `main` is simply:
-
-```haskell
-main = getArgs >>= doctest
-```
-
-Consequently, it is possible to create a custom executable for a project, by
-passing all command-line arguments that are required for that project to
-`doctest`.  A simple example looks like this:
-
-```haskell
--- file doctests.hs
-import Test.DocTest
-main = doctest ["-isrc", "src/Main.hs"]
-```
-
-And a corresponding Cabal test suite section like this:
-
-    test-suite doctests
-      type:          exitcode-stdio-1.0
-      ghc-options:   -threaded
-      main-is:       doctests.hs
-      build-depends: base, doctest >= 0.8
-
-## Doctest in the wild
-
-You can find real world examples of `Doctest` being used below:
-
-  * [base Data/Maybe.hs](https://github.com/ghc/ghc/blob/669cbef03c220de43b0f88f2b2238bf3c02ed64c/libraries/base/Data/Maybe.hs#L36-L79)
-  * [base Data/Functor.hs](https://github.com/ghc/ghc/blob/669cbef03c220de43b0f88f2b2238bf3c02ed64c/libraries/base/Data/Functor.hs#L34-L64)
-
-
-## Doctest extensions
-
-  * [doctest-discover](https://github.com/karun012/doctest-discover)
-
-## Development [![Build Status](https://secure.travis-ci.org/sol/doctest.png)](http://travis-ci.org/sol/doctest)
-
-Join in at `#hspec` on freenode.
-
-Discuss your ideas first, ideally by opening an issue on GitHub.
-
-Add tests for new features, and make sure that the test suite passes with your
-changes.
-
-    cabal configure --enable-tests && cabal build && cabal exec cabal test
-
-
-## Contributors
-
- * Adam Vogt
- * Alan Zimmerman
- * Alexander Bernauer
- * Alexandre Esteves
- * Anders Persson
- * Andreas Abel
- * Ankit Ahuja
- * Artyom Kazak
- * Edward Kmett
- * Gabor Greif
- * Hiroki Hattori
- * Ignat Insarov
- * Jens Petersen
- * Joachim Breitner
- * John Chee
- * João Cristóvão
- * Julian Arni
- * Kazu Yamamoto
- * Leon Schoorl
- * Levent Erkok
- * Luke Murphy
- * Matvey Aksenov
- * Michael Orlitzky
- * Michael Snoyman
- * Mitchell Rosen
- * Nick Smallbone
- * Nikos Baxevanis
- * Oleg Grenrus
- * quasicomputational
- * Ryan Scott
- * Sakari Jokinen
- * Simon Hengel
- * Sönke Hahn
- * Takano Akio
- * Tamar Christina
- * Veronika Romashkina
-
-For up-to-date list, query
-
-    git shortlog -s
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,533 @@
+# Doctest: Test interactive Haskell examples
+
+`doctest` is a tool that checks
+[examples](https://www.haskell.org/haddock/doc/html/ch03s08.html#idm140354810775744)
+and
+[properties](https://www.haskell.org/haddock/doc/html/ch03s08.html#idm140354810771856)
+in Haddock comments.
+It is similar in spirit to the [popular Python module with the same name](https://docs.python.org/3/library/doctest.html).
+
+* [Getting started](#getting-started)
+   * [Installation](#installation)
+   * [A basic example](#a-basic-example)
+   * [Running doctest for a Cabal package](#running-doctest-for-a-cabal-package)
+* [Writing examples and properties](#writing-examples-and-properties)
+   * [Example groups](#example-groups)
+      * [A note on performance](#a-note-on-performance)
+   * [Setup code](#setup-code)
+   * [Multi-line input](#multi-line-input)
+   * [Multi-line output](#multi-line-output)
+   * [Matching arbitrary output](#matching-arbitrary-output)
+   * [QuickCheck properties](#quickcheck-properties)
+   * [Hiding examples from Haddock](#hiding-examples-from-haddock)
+   * [Using GHC extensions](#using-ghc-extensions)
+* [Limitations](#limitations)
+* [Doctest in the wild](#doctest-in-the-wild)
+* [Development](#development)
+* [Contributors](#contributors)
+
+
+# Getting started
+
+## Installation
+
+`doctest` is available from
+[Hackage](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/doctest).
+Install it with:
+
+    cabal update && cabal install doctest
+
+Make sure that Cabal's `bindir` is on your `PATH`.
+
+On Linux:
+
+    export PATH="$HOME/.cabal/bin:$PATH"
+
+On Mac OS X:
+
+    export PATH="$HOME/Library/Haskell/bin:$PATH"
+
+On Windows:
+
+    set PATH="%AppData%\cabal\bin\;%PATH%"
+
+## A basic example
+
+Below is a small Haskell module.
+The module contains a Haddock comment with some examples of interaction.
+The examples demonstrate how the module is supposed to be used.
+
+```haskell
+-- src/Fib.hs
+module Fib where
+
+-- | Compute Fibonacci numbers
+--
+-- Examples:
+--
+-- >>> fib 10
+-- 55
+--
+-- >>> fib 5
+-- 5
+fib :: Int -> Int
+fib 0 = 0
+fib 1 = 1
+fib n = fib (n - 1) + fib (n - 2)
+
+```
+
+(A comment line starting with `>>>` denotes an _expression_.
+All comment lines following an expression denote the _result_ of that expression.
+Result is defined by what a
+[REPL](http://en.wikipedia.org/wiki/Read-eval-print_loop) (e.g. ghci)
+prints to `stdout` and `stderr` when evaluating that expression.)
+
+With `doctest` you can check whether the implementation satisfies the given
+examples:
+
+```
+doctest src/Fib.hs
+```
+
+
+## Running `doctest` for a Cabal package
+
+The easiest way to run `doctest` for a Cabal package is via `cabal repl --with-ghc=doctest`.
+
+This doesn't make a big difference for a simple package, but in more involved
+situations `cabal` will make sure that all dependencies are available and it
+will pass any required GHC options to `doctest`.
+
+A simple `.cabal` file for `Fib` looks like this:
+
+```cabal
+-- fib.cabal
+cabal-version: 1.12
+
+name:           fib
+version:        0.0.0
+build-type:     Simple
+
+library
+  build-depends: base == 4.*
+  hs-source-dirs: src
+  exposed-modules: Fib
+  default-language: Haskell2010
+
+```
+
+With a `.cabal` file in place, it is possible to run `doctest` via `cabal repl`:
+
+```
+$ cabal repl --with-ghc=doctest
+...
+Examples: 2  Tried: 2  Errors: 0  Failures: 0
+```
+
+
+Notes:
+
+- If you use properties you need to pass `--build-depends=QuickCheck` and
+  `--build-depends=template-haskell` to `cabal repl`.
+
+- `doctest` always uses the version of GHC it was compiled with.  Reinstalling
+  `doctest` with `cabal install doctest --overwrite-policy=always` before each
+  invocation ensures that it uses the same version of GHC as is on the `PATH`.
+- Technically, `cabal build` is not necessary. `cabal repl --with-ghc=doctest`
+  will build any dependencies as needed.  However, it's more robust to run
+  `cabal build` first (specifically it is not a good idea to build
+  `ghc-paths` with `--with-ghc=doctest`).
+
+So a more robust way to call `doctest` is as follows:
+
+```
+cabal install doctest --overwrite-policy=always && cabal build && cabal repl --build-depends=QuickCheck --build-depends=template-haskell --with-ghc=doctest
+```
+
+(This is what you want to use on CI.)
+
+
+# Writing examples and properties
+
+## Example groups
+
+Examples from a single Haddock comment are grouped together and share the same
+scope.  E.g. the following works:
+
+```haskell
+-- |
+-- >>> let x = 23
+-- >>> x + 42
+-- 65
+```
+
+If an example fails, subsequent examples from the same group are skipped.  E.g.
+for
+
+```haskell
+-- |
+-- >>> let x = 23
+-- >>> let n = x + y
+-- >>> print n
+```
+
+`print n` is skipped, because `let n = x + y` fails (as `y` is not in scope).
+
+### A note on performance
+
+By default, `doctest` calls `:reload` between each group to clear GHCi's scope
+of any local definitions. This ensures that previous examples cannot influence
+later ones. However, it can lead to performance penalties if you are using
+`doctest` in a project with many modules. One possible remedy is to pass the
+`--fast` flag to `doctest`, which disables calling `:reload` between groups.
+If `doctest`s are running too slowly, you might consider using `--fast`.
+(With the caveat that the order in which groups appear now matters!)
+
+However, note that due to a
+[bug on GHC 8.2.1 or later](https://ghc.haskell.org/trac/ghc/ticket/14052),
+the performance of `--fast` suffers significantly when combined with the
+`--preserve-it` flag (which keeps the value of GHCi's `it` value between
+examples).
+
+## Setup code
+
+You can put setup code in a [named chunk][named-chunks] with the name `$setup`.
+The setup code is run before each example group.  If the setup code produces
+any errors/failures, all tests from that module are skipped.
+
+Here is an example:
+
+```haskell
+module Foo where
+
+import Bar.Baz
+
+-- $setup
+-- >>> let x = 23 :: Int
+
+-- |
+-- >>> foo + x
+-- 65
+foo :: Int
+foo = 42
+```
+
+Note that you should not place setup code inbetween the module header (`module
+...  where`) and import declarations. GHC will not be able to parse it ([issue
+ #167](https://github.com/sol/doctest/issues/167)). It is best to place setup
+code right after import declarations, but due to its declarative nature you can
+place it anywhere inbetween top level declarations as well.
+
+
+## Multi-line input
+GHCi supports commands which span multiple lines, and the same syntax works for doctest:
+
+```haskell
+-- |
+-- >>> :{
+--  let
+--    x = 1
+--    y = 2
+--  in x + y + multiline
+-- :}
+-- 6
+multiline = 3
+```
+
+Note that `>>>` can be left off for the lines following the first: this is so that
+haddock does not strip leading whitespace. The expected output has whitespace
+stripped relative to the :}.
+
+Some peculiarities on the ghci side mean that whitespace at the very start is lost.
+This breaks the example `broken`, since the x and y aren't aligned from ghci's
+perspective.  A workaround is to avoid leading space, or add a newline such
+that the indentation does not matter:
+
+```haskell
+{- | >>> :{
+let x = 1
+    y = 2
+  in x + y + works
+:}
+6
+-}
+works = 3
+
+{- | >>> :{
+ let x = 1
+     y = 2
+  in x + y + broken
+:}
+3
+-}
+broken = 3
+```
+
+## Multi-line output
+If there are no blank lines in the output, multiple lines are handled
+automatically.
+
+```haskell
+-- | >>> putStr "Hello\nWorld!"
+-- Hello
+-- World!
+```
+
+If however the output contains blank lines, they must be noted
+explicitly with `<BLANKLINE>`. For example,
+
+```haskell
+import Data.List ( intercalate )
+
+-- | Double-space a paragraph.
+--
+--   Examples:
+--
+--   >>> let s1 = "\"Every one of whom?\""
+--   >>> let s2 = "\"Every one of whom do you think?\""
+--   >>> let s3 = "\"I haven't any idea.\""
+--   >>> let paragraph = unlines [s1,s2,s3]
+--   >>> putStrLn $ doubleSpace paragraph
+--   "Every one of whom?"
+--   <BLANKLINE>
+--   "Every one of whom do you think?"
+--   <BLANKLINE>
+--   "I haven't any idea."
+--
+doubleSpace :: String -> String
+doubleSpace = (intercalate "\n\n") . lines
+```
+
+## Matching arbitrary output
+Any lines containing only three dots (`...`) will match one or more lines with
+arbitrary content. For instance,
+
+```haskell
+-- |
+-- >>> putStrLn "foo\nbar\nbaz"
+-- foo
+-- ...
+-- baz
+```
+
+If a line contains three dots and additional content, the three dots will match
+anything *within that line*:
+
+```haskell
+-- |
+-- >>> putStrLn "foo bar baz"
+-- foo ... baz
+```
+
+## QuickCheck properties
+
+Haddock has markup support for properties.  Doctest can verify properties with
+QuickCheck.  A simple property looks like this:
+
+```haskell
+-- |
+-- prop> \xs -> sort xs == (sort . sort) (xs :: [Int])
+```
+
+The lambda abstraction is optional and can be omitted:
+
+```haskell
+-- |
+-- prop> sort xs == (sort . sort) (xs :: [Int])
+```
+
+A complete example that uses setup code is below:
+
+```haskell
+module Fib where
+
+-- $setup
+-- >>> import Control.Applicative
+-- >>> import Test.QuickCheck
+-- >>> newtype Small = Small Int deriving Show
+-- >>> instance Arbitrary Small where arbitrary = Small . (`mod` 10) <$> arbitrary
+
+-- | Compute Fibonacci numbers
+--
+-- The following property holds:
+--
+-- prop> \(Small n) -> fib n == fib (n + 2) - fib (n + 1)
+fib :: Int -> Int
+fib 0 = 0
+fib 1 = 1
+fib n = fib (n - 1) + fib (n - 2)
+```
+
+If you see an error like the following, ensure that
+[QuickCheck](http://hackage.haskell.org/package/QuickCheck) is visible to
+`doctest` (e.g. by passing `--build-depends=QuickCheck` to `cabal repl`).
+
+```haskell
+<interactive>:39:3:
+    Not in scope: ‘polyQuickCheck’
+    In the splice: $(polyQuickCheck (mkName "doctest_prop"))
+
+<interactive>:39:3:
+    GHC stage restriction:
+      ‘polyQuickCheck’ is used in a top-level splice or annotation,
+      and must be imported, not defined locally
+    In the expression: polyQuickCheck (mkName "doctest_prop")
+    In the splice: $(polyQuickCheck (mkName "doctest_prop"))
+```
+
+## Hiding examples from Haddock
+
+You can put examples into [named chunks][named-chunks], and not refer to them
+in the export list.  That way they will not be part of the generated Haddock
+documentation, but Doctest will still find them.
+
+```haskell
+-- $
+-- >>> 1 + 1
+-- 2
+```
+
+[named-chunks]: http://www.haskell.org/haddock/doc/html/ch03s05.html
+
+## Using GHC extensions
+
+There's two sets of GHC extensions involved when running Doctest:
+
+1. The set of GHC extensions that are active when compiling the module code
+   (excluding the doctest examples). The easiest way to specify these
+   extensions is through [LANGUAGE pragmas][language-pragma] in your source
+   files.
+
+1. The set of GHC extensions that are active when executing the Doctest
+   examples. (These are not influenced by the LANGUAGE pragmas in the file.)
+   The recommended way to enable extensions for Doctest examples is to switch
+   them on like this:
+
+```haskell
+-- |
+-- >>> :set -XTupleSections
+-- >>> fst' $ (1,) 2
+-- 1
+fst' :: (a, b) -> a
+fst' = fst
+```
+
+Alternatively you can pass any GHC options to Doctest, e.g.:
+
+    doctest -XCPP Foo.hs
+
+These options will affect both the loading of the module and the execution of
+the Doctest examples.
+
+If you want to omit the information which language extensions are enabled from
+the Doctest examples you can use the method described in [Hiding examples from
+Haddock](#hiding-examples-from-haddock), e.g.:
+
+```haskell
+-- $
+-- >>> :set -XTupleSections
+```
+
+[language-pragma]: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/exts/pragmas.html#language-pragma
+
+# Limitations
+
+
+- Doctests only works on platforms that have support for GHC's `--interactive` mode (`ghci`).
+
+
+- Due to [a GHC bug](https://gitlab.haskell.org/ghc/ghc/-/issues/20670), running
+  `:set -XTemplateHaskell` within `ghci` may unload any modules that were
+  specified on the command-line.
+
+  To address this `doctest >= 0.19.0` does two things:
+
+  1. Doctest always enables `-XTemplateHaskell`.  So it is safe to use Template
+    Haskell in examples without enabling the extension explicitly.
+  1. Doctest filters out `-XTemplateHaskell` from single-line `:set`-statements.
+    So it is still safe to include `:set -XTemplateHaskell` in examples for
+    documentation purposes.  It may just not work as intended in `ghci` due to
+    that GHC bug.
+
+  Doctest does not filter out `-XTemplateHaskell` from multi-line
+  `:set`-statements.  So if you e.g. use
+
+  ```
+  >>> :{
+  :set -XTemplateHaskell
+  :}
+  ```
+  then you are on your own.
+
+  Note that all platforms that support `--interactive` also support
+  `-XTemplateHaskell`.  So this approach does not reduce Doctest's platform
+  support.
+
+- Modules that are rejected by `haddock` will not work with `doctest`.  This
+  can mean that `doctest` fails on input that is accepted by GHC (e.g.
+  [#251](https://github.com/sol/doctest/issues/251)).
+
+- Doctest works best with UTF-8.  If your locale is e.g. `LC_ALL=C`, you may
+  want to invoke `doctest` with `LC_ALL=C.UTF-8`.
+
+# Doctest in the wild
+
+You can find real world examples of `Doctest` being used below:
+
+  * [base Data/Maybe.hs](https://github.com/ghc/ghc/blob/669cbef03c220de43b0f88f2b2238bf3c02ed64c/libraries/base/Data/Maybe.hs#L36-L79)
+  * [base Data/Functor.hs](https://github.com/ghc/ghc/blob/669cbef03c220de43b0f88f2b2238bf3c02ed64c/libraries/base/Data/Functor.hs#L34-L64)
+
+
+# Development
+
+Discuss your ideas first, ideally by opening an issue on GitHub.
+
+Add tests for new features, and make sure that the test suite passes with your
+changes.
+
+    cabal build --enable-tests && cabal exec -- cabal test --test-show-details=direct
+
+
+# Contributors
+
+ * Adam Vogt
+ * Alan Zimmerman
+ * Alexander Bernauer
+ * Alexandre Esteves
+ * Anders Persson
+ * Andreas Abel
+ * Ankit Ahuja
+ * Artyom Kazak
+ * Edward Kmett
+ * Gabor Greif
+ * Hiroki Hattori
+ * Ignat Insarov
+ * Jens Petersen
+ * Joachim Breitner
+ * John Chee
+ * João Cristóvão
+ * Julian Arni
+ * Kazu Yamamoto
+ * Leon Schoorl
+ * Levent Erkok
+ * Luke Murphy
+ * Matvey Aksenov
+ * Michael Orlitzky
+ * Michael Snoyman
+ * Mitchell Rosen
+ * Nick Smallbone
+ * Nikos Baxevanis
+ * Oleg Grenrus
+ * quasicomputational
+ * Ryan Scott
+ * Sakari Jokinen
+ * Simon Hengel
+ * Sönke Hahn
+ * Takano Akio
+ * Tamar Christina
+ * Veronika Romashkina
+
+For up-to-date list, query
+
+    git shortlog -s
diff --git a/doctest.cabal b/doctest.cabal
--- a/doctest.cabal
+++ b/doctest.cabal
@@ -1,14 +1,16 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.34.4.
+-- This file has been generated from package.yaml by hpack version 0.35.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           doctest
-version:        0.20.0
+version:        0.20.1
 synopsis:       Test interactive Haskell examples
-description:    The doctest program checks examples in source code comments.  It is modeled
-                after doctest for Python (<https://docs.python.org/3/library/doctest.html>).
+description:    `doctest` is a tool that checks [examples](https://www.haskell.org/haddock/doc/html/ch03s08.html#idm140354810775744)
+                and [properties](https://www.haskell.org/haddock/doc/html/ch03s08.html#idm140354810771856)
+                in Haddock comments.
+                It is similar in spirit to the [popular Python module with the same name](https://docs.python.org/3/library/doctest.html).
                 .
                 Documentation is at <https://github.com/sol/doctest#readme>.
 category:       Testing
@@ -16,7 +18,7 @@
 homepage:       https://github.com/sol/doctest#readme
 license:        MIT
 license-file:   LICENSE
-copyright:      (c) 2009-2018 Simon Hengel
+copyright:      (c) 2009-2022 Simon Hengel
 author:         Simon Hengel <sol@typeful.net>
 maintainer:     quasicomputational@gmail.com, Andreas Abel
 build-type:     Simple
@@ -99,7 +101,7 @@
     test/integration/with-cbits/Bar.hs
     test/integration/with-cbits/foo.c
     CHANGES.markdown
-    README.markdown
+    README.md
 
 source-repository head
   type: git
@@ -136,7 +138,7 @@
     , directory
     , exceptions
     , filepath
-    , ghc >=7.0 && <9.3
+    , ghc >=8.0 && <9.5
     , ghc-paths >=0.1.0.9
     , process
     , syb >=0.3
@@ -159,7 +161,7 @@
     , doctest
     , exceptions
     , filepath
-    , ghc >=7.0 && <9.3
+    , ghc >=8.0 && <9.5
     , ghc-paths >=0.1.0.9
     , process
     , syb >=0.3
@@ -220,7 +222,7 @@
     , directory
     , exceptions
     , filepath
-    , ghc >=7.0 && <9.3
+    , ghc >=8.0 && <9.5
     , ghc-paths >=0.1.0.9
     , hspec >=2.3.0
     , hspec-core >=2.3.0
diff --git a/src/Extract.hs b/src/Extract.hs
--- a/src/Extract.hs
+++ b/src/Extract.hs
@@ -3,23 +3,14 @@
 
 import           Prelude hiding (mod, concat)
 import           Control.Monad
-#if __GLASGOW_HASKELL__ < 710
-import           Control.Applicative
-#endif
 import           Control.Exception
 import           Data.List (partition, isSuffixOf)
 import           Data.Maybe
-#if __GLASGOW_HASKELL__ < 710
-import           Data.Foldable (concat)
-#endif
 
 import           Control.DeepSeq (deepseq, NFData(rnf))
 import           Data.Generics
 
-#if __GLASGOW_HASKELL__ < 707
-import           GHC hiding (flags, Module, Located)
-import           MonadUtils (liftIO, MonadIO)
-#elif __GLASGOW_HASKELL__ < 900
+#if __GLASGOW_HASKELL__ < 900
 import           GHC hiding (Module, Located)
 import           DynFlags
 import           MonadUtils (liftIO)
@@ -41,11 +32,6 @@
 import           System.Directory
 import           System.FilePath
 
-#if __GLASGOW_HASKELL__ < 710
-import           NameSet (NameSet)
-import           Coercion (Coercion)
-#endif
-
 #if __GLASGOW_HASKELL__ < 805
 import           FastString (unpackFS)
 #endif
@@ -137,15 +123,11 @@
     modifySessionDynFlags :: (DynFlags -> DynFlags) -> Ghc ()
     modifySessionDynFlags f = do
       dflags <- getSessionDynFlags
-#if __GLASGOW_HASKELL__ < 707
-      _ <- setSessionDynFlags (f dflags)
-#else
       -- GHCi 7.7 now uses dynamic linking.
       let dflags' = case lookup "GHC Dynamic" (compilerInfo dflags) of
             Just "YES" -> gopt_set dflags Opt_BuildDynamicToo
             _          -> dflags
       _ <- setSessionDynFlags (f dflags')
-#endif
       return ()
 
     withTempOutputDir :: Ghc a -> Ghc a
@@ -181,11 +163,7 @@
       _ <- setSessionDynFlags (GHC.ms_hspp_opts modsum)
       hsc_env <- getSession
 
-# if __GLASGOW_HASKELL__ >= 903
-      hsc_env' <- liftIO (initializePlugins hsc_env Nothing)
-      setSession hsc_env'
-      return $ modsum
-# elif __GLASGOW_HASKELL__ >= 901
+# if __GLASGOW_HASKELL__ >= 902
       hsc_env' <- liftIO (initializePlugins hsc_env)
       setSession hsc_env'
       return $ modsum
@@ -225,6 +203,11 @@
     (setup, docs) = partition isSetup (docStringsFromModule m)
     name = (moduleNameString . GHC.moduleName . ms_mod . pm_mod_summary) m
 
+#if __GLASGOW_HASKELL__ >= 904
+unpackHDS :: HsDocString -> String
+unpackHDS = renderHsDocString
+#endif
+
 -- | Extract all docstrings from given module.
 docStringsFromModule :: ParsedModule -> [(Maybe String, Located String)]
 docStringsFromModule mod = map (fmap (toLocated . fmap unpackHDS)) docs
@@ -232,66 +215,58 @@
     source   = (unLoc . pm_parsed_source) mod
 
     -- we use dlist-style concatenation here
+    docs :: [(Maybe String, LHsDocString)]
     docs     = header ++ exports ++ decls
 
     -- We process header, exports and declarations separately instead of
     -- traversing the whole source in a generic way, to ensure that we get
     -- everything in source order.
+#if __GLASGOW_HASKELL__ >= 904
+    header  = [(Nothing, hsDocString <$> x) | Just x <- [hsmodHaddockModHeader source]]
+#else
     header  = [(Nothing, x) | Just x <- [hsmodHaddockModHeader source]]
+#endif
+    exports :: [(Maybe String, LHsDocString)]
+#if __GLASGOW_HASKELL__ >= 904
+    exports = [ (Nothing, L (locA loc) (hsDocString (unLoc doc)))
+#else
     exports = [ (Nothing, L (locA loc) doc)
-#if __GLASGOW_HASKELL__ < 710
-              | L loc (IEDoc doc) <- concat (hsmodExports source)
-#elif __GLASGOW_HASKELL__ < 805
+#endif
+#if __GLASGOW_HASKELL__ < 805
               | L loc (IEDoc doc) <- maybe [] unLoc (hsmodExports source)
 #else
               | L loc (IEDoc _ doc) <- maybe [] unLoc (hsmodExports source)
 #endif
               ]
+    decls :: [(Maybe String, LHsDocString)]
     decls   = extractDocStrings (hsmodDecls source)
 
-type Selector a = a -> ([(Maybe String, LHsDocString)], Bool)
-
-#if __GLASGOW_HASKELL__ < 710
--- | Ignore a subtree.
-ignore :: Selector a
-ignore = const ([], True)
-#endif
-
--- | Collect given value and descend into subtree.
-select :: a -> ([a], Bool)
-select x = ([x], False)
-
 -- | Extract all docstrings from given value.
 extractDocStrings :: Data a => a -> [(Maybe String, LHsDocString)]
-extractDocStrings = everythingBut (++) (([], False) `mkQ` fromLHsDecl
-  `extQ` fromLDocDecl
-  `extQ` fromLHsDocString
-#if __GLASGOW_HASKELL__ < 710
-  `extQ` (ignore :: Selector NameSet)
-  `extQ` (ignore :: Selector PostTcKind)
-
-  -- HsExpr never contains any documentation, but it may contain error thunks.
-  --
-  -- Problematic are (non comprehensive):
-  --
-  --  * parallel list comprehensions
-  --  * infix operators
-  --
-  `extQ` (ignore :: Selector (HsExpr RdrName))
-
-  -- undefined before type checking
-  `extQ` (ignore :: Selector Coercion)
+extractDocStrings d =
+#if __GLASGOW_HASKELL__ >= 904
+  let
+    docStrs = extractAll extractDocDocString d
+    docStrNames = catMaybes $ extractAll extractDocName d
+  in
+    flip fmap docStrs $ \docStr -> (lookup (getLoc docStr) docStrNames, docStr)
+  where
+    extractAll z = everything (++) ((mkQ [] ((:[]) . z)))
 
-#if __GLASGOW_HASKELL__ >= 706
-  -- hswb_kvs and hswb_tvs may be error thunks
-  `extQ` (ignore :: Selector (HsWithBndrs [LHsType RdrName]))
-  `extQ` (ignore :: Selector (HsWithBndrs [LHsType Name]))
-  `extQ` (ignore :: Selector (HsWithBndrs (LHsType RdrName)))
-  `extQ` (ignore :: Selector (HsWithBndrs (LHsType Name)))
-#endif
+    extractDocDocString :: LHsDoc GhcPs -> LHsDocString
+    extractDocDocString = fmap hsDocString
 
-#endif
-  )
+    extractDocName :: DocDecl GhcPs -> Maybe (SrcSpan, String)
+    extractDocName docDecl = case docDecl of
+      DocCommentNamed name y ->
+        Just (getLoc y, name)
+      _ ->
+        Nothing
+#else
+  everythingBut (++) (([], False) `mkQ` fromLHsDecl
+  `extQ` fromLDocDecl
+  `extQ` fromLHsDocString
+  ) d
   where
     fromLHsDecl :: Selector (LHsDecl GhcPs)
     fromLHsDecl (L loc decl) = case decl of
@@ -323,6 +298,13 @@
     fromDocDecl loc x = case x of
       DocCommentNamed name doc -> (Just name, L loc doc)
       _                        -> (Nothing, L loc $ docDeclDoc x)
+
+type Selector a = a -> ([(Maybe String, LHsDocString)], Bool)
+
+-- | Collect given value and descend into subtree.
+select :: a -> ([a], Bool)
+select x = ([x], False)
+#endif
 
 #if __GLASGOW_HASKELL__ < 805
 -- | Convert a docstring to a plain string.
diff --git a/src/GhcUtil.hs b/src/GhcUtil.hs
--- a/src/GhcUtil.hs
+++ b/src/GhcUtil.hs
@@ -2,18 +2,12 @@
 module GhcUtil (withGhc) where
 
 import           GHC.Paths (libdir)
-#if __GLASGOW_HASKELL__ < 707
-import           Control.Exception
-import           GHC hiding (flags)
-import           DynFlags (dopt_set)
-#else
 import           GHC
 #if __GLASGOW_HASKELL__ < 900
 import           DynFlags (gopt_set)
 #else
 import           GHC.Driver.Session (gopt_set)
 #endif
-#endif
 
 #if __GLASGOW_HASKELL__ < 900
 import           Panic (throwGhcException)
@@ -29,50 +23,26 @@
 
 import           System.Exit (exitFailure)
 
-#if __GLASGOW_HASKELL__ < 702
-import           StaticFlags (v_opt_C_ready)
-import           Data.IORef (writeIORef)
-#elif __GLASGOW_HASKELL__ < 707
-import           StaticFlags (saveStaticFlagGlobals, restoreStaticFlagGlobals)
-#elif __GLASGOW_HASKELL__ < 801
+#if __GLASGOW_HASKELL__ < 801
 import           StaticFlags (discardStaticFlags)
 #endif
 
-
--- | Save static flag globals, run action, and restore them.
-bracketStaticFlags :: IO a -> IO a
-#if __GLASGOW_HASKELL__ < 702
--- GHC < 7.2 does not provide saveStaticFlagGlobals/restoreStaticFlagGlobals,
--- so we need to modifying v_opt_C_ready directly
-bracketStaticFlags action = action `finally` writeIORef v_opt_C_ready False
-#elif __GLASGOW_HASKELL__ < 707
-bracketStaticFlags action = bracket saveStaticFlagGlobals restoreStaticFlagGlobals (const action)
-#else
-bracketStaticFlags action = action
-#endif
-
 -- Catch GHC source errors, print them and exit.
 handleSrcErrors :: Ghc a -> Ghc a
 handleSrcErrors action' = flip handleSourceError action' $ \err -> do
-#if __GLASGOW_HASKELL__ < 702
-  printExceptionAndWarnings err
-#else
   printException err
-#endif
   liftIO exitFailure
 
 -- | Run a GHC action in Haddock mode
 withGhc :: [String] -> ([String] -> Ghc a) -> IO a
-withGhc flags action = bracketStaticFlags $ do
+withGhc flags action = do
   flags_ <- handleStaticFlags flags
 
   runGhc (Just libdir) $ do
     handleDynamicFlags flags_ >>= handleSrcErrors . action
 
 handleStaticFlags :: [String] -> IO [Located String]
-#if __GLASGOW_HASKELL__ < 707
-handleStaticFlags flags = fst `fmap` parseStaticFlags (map noLoc flags)
-#elif __GLASGOW_HASKELL__ < 801
+#if __GLASGOW_HASKELL__ < 801
 handleStaticFlags flags = return $ map noLoc $ discardStaticFlags flags
 #else
 handleStaticFlags flags = return $ map noLoc $ flags
@@ -98,11 +68,7 @@
     _       -> return srcs
 
 setHaddockMode :: DynFlags -> DynFlags
-#if __GLASGOW_HASKELL__ < 707
-setHaddockMode dynflags = (dopt_set dynflags Opt_Haddock) {
-#else
 setHaddockMode dynflags = (gopt_set dynflags Opt_Haddock) {
-#endif
 #if __GLASGOW_HASKELL__ >= 901
       backend   = NoBackend
 #else
diff --git a/src/Interpreter.hs b/src/Interpreter.hs
--- a/src/Interpreter.hs
+++ b/src/Interpreter.hs
@@ -16,9 +16,6 @@
 
 import           System.Process
 import           System.Directory (getPermissions, executable)
-#if __GLASGOW_HASKELL__ < 710
-import           Control.Applicative
-#endif
 import           Control.Monad
 import           Control.Exception hiding (handle)
 import           Data.Char
diff --git a/src/Location.hs b/src/Location.hs
--- a/src/Location.hs
+++ b/src/Location.hs
@@ -13,10 +13,6 @@
 import           GHC.Data.FastString (unpackFS)
 #endif
 
-#if __GLASGOW_HASKELL__ < 702
-import           Outputable (showPpr)
-#endif
-
 -- | A thing with a location attached.
 data Located a = Located Location a
   deriving (Eq, Show, Functor)
@@ -61,13 +57,7 @@
 
 -- | Convert a GHC source span to a location.
 toLocation :: SrcSpan -> Location
-#if __GLASGOW_HASKELL__ < 702
-toLocation loc
-  | isGoodSrcLoc start = Location (unpackFS $ srcLocFile start) (srcLocLine start)
-  | otherwise          = (UnhelpfulLocation . showPpr) start
-  where
-    start = srcSpanStart loc
-#elif __GLASGOW_HASKELL__ < 900
+#if __GLASGOW_HASKELL__ < 900
 toLocation loc = case loc of
   UnhelpfulSpan str -> UnhelpfulLocation (unpackFS str)
   RealSrcSpan sp    -> Location (unpackFS . srcSpanFile $ sp) (srcSpanStartLine sp)
diff --git a/src/PackageDBs.hs b/src/PackageDBs.hs
--- a/src/PackageDBs.hs
+++ b/src/PackageDBs.hs
@@ -1,14 +1,12 @@
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE PatternGuards #-}
 -- | Manage GHC package databases
-module PackageDBs
-    ( PackageDBs (..)
-    , ArgStyle (..)
-    , dbArgs
-    , buildArgStyle
-    , getPackageDBsFromEnv
-    , getPackageDBArgs
-    ) where
+module PackageDBs (
+  getPackageDBArgs
+#ifdef TEST
+, PackageDBs (..)
+, getPackageDBsFromEnv
+#endif
+) where
 
 import System.Environment (getEnvironment)
 import System.FilePath (splitSearchPath, searchPathSeparator)
@@ -16,42 +14,24 @@
 -- | Full stack of GHC package databases
 data PackageDBs = PackageDBs
     { includeUser :: Bool
-    -- | Unsupported on GHC < 7.6
     , includeGlobal :: Bool
     , extraDBs :: [FilePath]
     }
     deriving (Show, Eq)
 
--- | Package database handling switched between GHC 7.4 and 7.6
-data ArgStyle = Pre76 | Post76
-    deriving (Show, Eq)
-
 -- | Determine command line arguments to be passed to GHC to set databases correctly
 --
--- >>> dbArgs Post76 (PackageDBs False True [])
+-- >>> dbArgs (PackageDBs False True [])
 -- ["-no-user-package-db"]
 --
--- >>> dbArgs Pre76 (PackageDBs True True ["somedb"])
--- ["-package-conf","somedb"]
-dbArgs :: ArgStyle -> PackageDBs -> [String]
-dbArgs Post76 (PackageDBs user global extras) =
+-- >>> dbArgs (PackageDBs True True ["somedb"])
+-- ["-package-db","somedb"]
+dbArgs :: PackageDBs -> [String]
+dbArgs (PackageDBs user global extras) =
     (if user then id else ("-no-user-package-db":)) $
     (if global then id else ("-no-global-package-db":)) $
     concatMap (\extra -> ["-package-db", extra]) extras
-dbArgs Pre76 (PackageDBs _ False _) =
-    error "Global package database must be included with GHC < 7.6"
-dbArgs Pre76 (PackageDBs user True extras) =
-    (if user then id else ("-no-user-package-conf":)) $
-    concatMap (\extra -> ["-package-conf", extra]) extras
 
--- | The argument style to be used with the current GHC version
-buildArgStyle :: ArgStyle
-#if __GLASGOW_HASKELL__ >= 706
-buildArgStyle = Post76
-#else
-buildArgStyle = Pre76
-#endif
-
 -- | Determine the PackageDBs based on the environment.
 getPackageDBsFromEnv :: IO PackageDBs
 getPackageDBsFromEnv = do
@@ -79,4 +59,4 @@
 getPackageDBArgs :: IO [String]
 getPackageDBArgs = do
       dbs <- getPackageDBsFromEnv
-      return $ dbArgs buildArgStyle dbs
+      return $ dbArgs dbs
diff --git a/src/Parse.hs b/src/Parse.hs
--- a/src/Parse.hs
+++ b/src/Parse.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE PatternGuards #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE CPP #-}
 module Parse (
   Module (..)
 , DocTest (..)
@@ -21,9 +20,6 @@
 import           Data.List (isPrefixOf, stripPrefix)
 import           Data.Maybe
 import           Data.String
-#if __GLASGOW_HASKELL__ < 710
-import           Control.Applicative
-#endif
 import           Extract
 import           Location
 
diff --git a/src/Property.hs b/src/Property.hs
--- a/src/Property.hs
+++ b/src/Property.hs
@@ -67,7 +67,5 @@
 
     -- | Remove quotes from given name, if any.
     unquote ('`':xs)     = init xs
-#if __GLASGOW_HASKELL__ >= 707
     unquote ('\8216':xs) = init xs
-#endif
     unquote xs           = xs
diff --git a/src/Runner.hs b/src/Runner.hs
--- a/src/Runner.hs
+++ b/src/Runner.hs
@@ -13,11 +13,6 @@
 
 import           Prelude hiding (putStr, putStrLn, error)
 
-#if __GLASGOW_HASKELL__ < 710
-import           Data.Monoid hiding ((<>))
-import           Control.Applicative
-#endif
-
 import           Control.Monad hiding (forM_)
 import           Text.Printf (printf)
 import           System.IO (hPutStrLn, hPutStr, stderr, hIsTerminalDevice)
@@ -50,11 +45,11 @@
 -- | Sum up summaries.
 instance Monoid Summary where
   mempty = Summary 0 0 0 0
-#if MIN_VERSION_base(4,11,0)
+#if __GLASGOW_HASKELL__ < 804
+  mappend
+#else
 instance Semigroup Summary where
   (<>)
-#else
-  mappend
 #endif
     (Summary x1 x2 x3 x4) (Summary y1 y2 y3 y4) = Summary (x1 + y1) (x2 + y2) (x3 + y3) (x4 + y4)
 
diff --git a/test/PropertySpec.hs b/test/PropertySpec.hs
--- a/test/PropertySpec.hs
+++ b/test/PropertySpec.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP, OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings #-}
 module PropertySpec (main, spec) where
 
 import           Test.Hspec
@@ -30,17 +30,10 @@
       runProperty repl "(reverse . reverse) xs == (xs :: [Int])" `shouldReturn` Success
 
     it "runs an implicitly quantified property even with GHC 7.4" $
-#if __GLASGOW_HASKELL__ == 702
-      pendingWith "This triggers a bug in GHC 7.2.*."
-      -- try e.g.
-      -- >>> 23
-      -- >>> :t is
-#else
       -- ghc will include a suggestion (did you mean `id` instead of `is`) in
       -- the error message
       withInterpreter [] $ \repl -> do
         runProperty repl "foldr (+) 0 is == sum (is :: [Int])" `shouldReturn` Success
-#endif
 
     it "runs an explicitly quantified property" $ withInterpreter [] $ \repl -> do
       runProperty repl "\\xs -> (reverse . reverse) xs == (xs :: [Int])" `shouldReturn` Success
diff --git a/test/RunSpec.hs b/test/RunSpec.hs
--- a/test/RunSpec.hs
+++ b/test/RunSpec.hs
@@ -8,8 +8,10 @@
 import           System.Exit
 
 import qualified Control.Exception as E
+import           System.FilePath
 import           System.Directory (getCurrentDirectory, setCurrentDirectory)
 import           Data.List.Compat (isPrefixOf, sort)
+import           Data.Char
 
 import           System.IO.Silently
 import           System.IO (stderr)
@@ -126,24 +128,14 @@
 
       it "prints a useful error message" $ do
         (r, _) <- hCapture [stderr] (E.try action :: IO (Either ExitCode Summary))
-#if __GLASGOW_HASKELL__ < 706
-        r `shouldBe` "\nFoo.hs:6:1: parse error (possibly incorrect indentation)\n"
-#else
-
-#if __GLASGOW_HASKELL__ < 800
-        r `shouldBe` "\nFoo.hs:6:1:\n    parse error (possibly incorrect indentation or mismatched brackets)\n"
-#else
-        removeLoadedPackageEnvironment r `shouldBe` "\nFoo.hs:6:1: error:\n    parse error (possibly incorrect indentation or mismatched brackets)\n"
-#endif
-
-#endif
+        stripAnsiColors (removeLoadedPackageEnvironment r) `shouldBe` "\nFoo.hs:6:1: error:\n    parse error (possibly incorrect indentation or mismatched brackets)\n"
 
   describe "expandDirs" $ do
     it "expands a directory" $ do
       res <- expandDirs "example"
       sort res `shouldBe`
-        [ "example/src/Example.hs"
-        , "example/test/doctests.hs"
+        [ "example" </> "src" </> "Example.hs"
+        , "example" </> "test" </> "doctests.hs"
         ]
     it "ignores files" $ do
       res <- expandDirs "doctest.cabal"
@@ -152,3 +144,10 @@
       let x = "foo bar baz bin"
       res <- expandDirs x
       res `shouldBe` [x]
+
+stripAnsiColors :: String -> String
+stripAnsiColors xs = case xs of
+  '\ESC' : '[' : ';' : ys | 'm' : zs <- dropWhile isNumber ys -> stripAnsiColors zs
+  '\ESC' : '[' : ys | 'm' : zs <- dropWhile isNumber ys -> stripAnsiColors zs
+  y : ys -> y : stripAnsiColors ys
+  [] -> []
diff --git a/test/RunnerSpec.hs b/test/RunnerSpec.hs
--- a/test/RunnerSpec.hs
+++ b/test/RunnerSpec.hs
@@ -3,10 +3,6 @@
 
 import           Test.Hspec
 
-#if __GLASGOW_HASKELL__ < 710
-import           Data.Monoid
-#endif
-
 import           System.IO
 import           System.IO.Silently (hCapture)
 import           Control.Monad.Trans.State
