diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,14 +1,23 @@
 # Changelog and Acknowledgements
 
+## 2.1.0
+* Replaced `Proxy :: Proxy info` with type applications in splices from
+  `regex`/`_regex`.  This significantly shortens the splices, producing nicer
+  error messages.  As a very minor consequence, we now require the user to turn
+  on `{-# LANGUAGE TypeApplications #-}` when using `regex`/`_regex` with
+  patterns with parenthesized captures, even when not using
+  `capture`/`_capture`.
+
 ## 2.0.5
-* Enabled PCRE2's built-in Unicode support.
+* Enabled PCRE2's built-in Unicode support, which fixes
+  [#21](https://github.com/sjshuck/hs-pcre2/issues/21).
 
 ## 2.0.4
 * Added `Show` instance for `Captures` to ease debugging user code.
 
 ## 2.0.3
 * Updated PCRE2 to 10.39 (no API changes).  The C sources are now drawn from
-  https://github.com/PhilipHazel/pcre2.git, which fixes
+  https://github.com/PhilipHazel/pcre2, which fixes
   [#10](https://github.com/sjshuck/hs-pcre2/issues/10).
 
 ## 2.0.2
diff --git a/pcre2.cabal b/pcre2.cabal
--- a/pcre2.cabal
+++ b/pcre2.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           pcre2
-version:        2.0.5
+version:        2.1.0
 synopsis:       Regular expressions via the PCRE2 C library (included)
 description:    Please see the README on GitHub at <https://github.com/sjshuck/hs-pcre2>
 category:       Text
@@ -13,7 +13,7 @@
 bug-reports:    https://github.com/sjshuck/hs-pcre2/issues
 author:         Shlomo Shuck and contributors
 maintainer:     stevenjshuck@gmail.com
-copyright:      2020-2021 Shlomo Shuck
+copyright:      2020-2022 Shlomo Shuck
 license:        Apache-2.0
 license-file:   LICENSE
 build-type:     Simple
diff --git a/src/hs/Text/Regex/Pcre2.hs b/src/hs/Text/Regex/Pcre2.hs
--- a/src/hs/Text/Regex/Pcre2.hs
+++ b/src/hs/Text/Regex/Pcre2.hs
@@ -250,10 +250,12 @@
     -- |                    | other type-level data powering        | parenthesized captures       |
     -- |                    | compile-time capture lookups          |                              |
     -- +--------------------+---------------------------------------+------------------------------+
-    -- | @QuasiQuotes@      | @[@/f/@|@...@|]@ syntax               | Always                       |
+    -- | @QuasiQuotes@      | @[@/f/@|@...@|]@ syntax               | Using `regex`\/`_regex`      |
     -- +--------------------+---------------------------------------+------------------------------+
-    -- | @TypeApplications@ | @\@i@ syntax for supplying type index | Using `capture`\/`_capture`  |
-    -- |                    | arguments to applicable functions     |                              |
+    -- | @TypeApplications@ | @\@i@ syntax for supplying type index | Using `regex`\/`_regex` with |
+    -- |                    | arguments to applicable functions     | a pattern containing         |
+    -- |                    |                                       | parenthesized captures;      |
+    -- |                    |                                       | using `capture`\/`_capture`  |
     -- +--------------------+---------------------------------------+------------------------------+
     -- | @ViewPatterns@     | Running code and binding variables in | Using `regex` as a Haskell   |
     -- |                    | pattern context proper (pattern       | pattern                      |
diff --git a/src/hs/Text/Regex/Pcre2/TH.hs b/src/hs/Text/Regex/Pcre2/TH.hs
--- a/src/hs/Text/Regex/Pcre2/TH.hs
+++ b/src/hs/Text/Regex/Pcre2/TH.hs
@@ -56,12 +56,6 @@
 -- numbers.
 type CapturesInfo = (Nat, [(Symbol, Nat)])
 
--- | Helper for constructing an empty lookup table.  If we splice `promotedNilT`
--- directly, we would have to require the user to turn on either
--- @KindSignatures@ or @PolyKinds@; GHC seems to monokind @'[]@ as @[*]@,
--- instead of unifying it with the list inside `CapturesInfo`.
-type NoNamedCaptures = '[] :: [(Symbol, Nat)]
-
 -- | Look up the number of a capture at compile time, either by number or by
 -- name.  Throw a helpful 'TypeError' if the index doesn\'t exist.
 type family CaptNum (i :: k) (info :: CapturesInfo) :: Nat where
@@ -182,10 +176,7 @@
         -- 5
         hiQ = litT $ numTyLit $ fromIntegral $ length captureNames
         -- '[ '("foo", 1), '("bar", 4)]
-        kvsQ = case toKVs captureNames of
-            -- We can't splice '[] because it doesn't kind-check.  See above.
-            []  -> [t| NoNamedCaptures |]
-            kvs -> foldr f promotedNilT kvs
+        kvsQ = foldr f promotedNilT $ toKVs captureNames
         -- '("foo", 1) ': ...
         f (number, name) r = promotedConsT `appT` kvQ `appT` r where
             kvQ = promotedTupleT 2                           -- '(,)
@@ -197,8 +188,9 @@
 matchTH patt = toAlternativeOf $ _matchTH patt
 
 -- | Helper for `regex` with parenthesized captures.
-capturesTH :: (Alternative f) => Text -> Proxy info -> Text -> f (Captures info)
-capturesTH patt proxy = toAlternativeOf $ _capturesTH patt proxy
+capturesTH :: forall info f. (Alternative f) =>
+    Text -> Text -> f (Captures info)
+capturesTH patt = toAlternativeOf $ _capturesTH patt
 
 -- | Helper for `regex` as a guard pattern.
 matchesTH :: Text -> Text -> Bool
@@ -214,8 +206,8 @@
 _matchTH patt = _gcaptures (memoMatcher patt) get0thSlice . _Identity
 
 -- | Helper for `_regex` with parenthesized captures.
-_capturesTH :: Text -> Proxy info -> Traversal' Text (Captures info)
-_capturesTH patt _ = _gcaptures (memoMatcher patt) getAllSlices . captured where
+_capturesTH :: Text -> Traversal' Text (Captures info)
+_capturesTH patt = _gcaptures (memoMatcher patt) getAllSlices . captured where
     captured f cs = f (Captures cs) <&> \(Captures cs') -> cs'
 
 -- | === As an expression
@@ -259,11 +251,11 @@
 -- If there are no named captures, this simply acts as a guard.
 regex :: QuasiQuoter
 regex = QuasiQuoter{
-    quoteExp = \s -> capturesInfoQ s >>= \case
-        Nothing   -> [e| matchTH (Text.pack $(stringE s)) |]
-        Just info -> [e| capturesTH
-            (Text.pack $(stringE s))
-            (Proxy :: Proxy $(return info)) |],
+    quoteExp = \s -> do
+        let regexQ = capturesInfoQ s >>= \case
+                Nothing   -> [e| matchTH |]
+                Just info -> [e| capturesTH |] `appTypeE` return info
+        regexQ `appE` [e| Text.pack $(stringE s) |],
 
     quotePat = \s -> do
         captureNames <- predictCaptureNamesQ s
@@ -308,11 +300,11 @@
 -- > -- There are 15 competing standards
 _regex :: QuasiQuoter
 _regex = QuasiQuoter{
-    quoteExp = \s -> capturesInfoQ s >>= \case
-        Nothing   -> [e| _matchTH (Text.pack $(stringE s)) |]
-        Just info -> [e| _capturesTH
-            (Text.pack $(stringE s))
-            (Proxy :: Proxy $(return info)) |],
+    quoteExp = \s -> do
+        let _regexQ = capturesInfoQ s >>= \case
+                Nothing   -> [e| _matchTH |]
+                Just info -> [e| _capturesTH |] `appTypeE` return info
+        _regexQ `appE` [e| Text.pack $(stringE s) |],
 
     quotePat = const $ fail "_regex: cannot produce a pattern",
 
