diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.0.6.1
+
+* Documentation improvements
+
 ## 0.0.6.0
 
 * Add `withYieldToList`
diff --git a/bluefin-internal.cabal b/bluefin-internal.cabal
--- a/bluefin-internal.cabal
+++ b/bluefin-internal.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               bluefin-internal
-version:            0.0.6.0
+version:            0.0.6.1
 license:            MIT
 license-file:       LICENSE
 author:             Tom Ellis
@@ -77,7 +77,7 @@
     default-language: Haskell2010
     hs-source-dirs: src
     build-depends:
-      base >= 4.12 && < 4.20,
+      base >= 4.12 && < 4.21,
       unliftio-core < 0.3,
       transformers < 0.7,
       transformers-base < 0.5,
diff --git a/src/Bluefin/Internal.hs b/src/Bluefin/Internal.hs
--- a/src/Bluefin/Internal.hs
+++ b/src/Bluefin/Internal.hs
@@ -35,6 +35,7 @@
 type (:&) = Union
 
 type role Eff nominal representational
+
 newtype Eff (es :: Effects) a = UnsafeMkEff {unsafeUnEff :: IO a}
   deriving stock (Functor)
   deriving newtype (Applicative, Monad)
@@ -184,17 +185,17 @@
 useImplIn f h = inContext (f h)
 
 -- | Handle to a capability to create strict mutable state handles
-data StateSource (st :: Effects) = StateSource
+data StateSource (e :: Effects) = StateSource
 
--- | Handle to an exception of type @e@
-newtype Exception e (ex :: Effects) = UnsafeMkException (forall a. e -> IO a)
+-- | Handle to an exception of type @exn@
+newtype Exception exn (e :: Effects) = UnsafeMkException (forall a. exn -> IO a)
 
--- | A handle to a strict mutable state of type @a@
-newtype State s (st :: Effects) = UnsafeMkState (IORef s)
+-- | A handle to a strict mutable state of type @s@
+newtype State s (e :: Effects) = UnsafeMkState (IORef s)
 
 -- | A handle to a coroutine that expects values of type @a@ and then
 -- yields values of type @b@.
-newtype Coroutine a b (s :: Effects) = MkCoroutine (a -> Eff s b)
+newtype Coroutine a b (e :: Effects) = MkCoroutine (a -> Eff e b)
 
 -- | A handle to a stream that yields values of type @a@.  It is
 -- implemented as a handle to a coroutine that expects values of type
@@ -237,7 +238,6 @@
 -- fmap per @->@ that appears in type of the dynamic effect.  That is,
 -- @queryDatabase@ has type @String -> Int -> Eff e [String]@, which
 -- has two @->@, so there are two @fmap@s before @useImpl@.
-
 class Handle (h :: Effects -> Type) where
   -- | Used to create compound effects, i.e. handles that contain
   -- other handles.
@@ -356,10 +356,10 @@
 -- Left 42
 -- @
 try ::
-  forall e (es :: Effects) a.
-  (forall ex. Exception e ex -> Eff (ex :& es) a) ->
+  forall exn (es :: Effects) a.
+  (forall e. Exception exn e -> Eff (e :& es) a) ->
   -- | @Left@ if the exception was thrown, @Right@ otherwise
-  Eff es (Either e a)
+  Eff es (Either exn a)
 try f =
   UnsafeMkEff $ withScopedException_ (\throw_ -> unsafeUnEff (f (UnsafeMkException throw_)))
 
@@ -372,10 +372,10 @@
 -- "42"
 -- @
 handle ::
-  forall e (es :: Effects) a.
+  forall exn (es :: Effects) a.
   -- | If the exception is thrown, apply this handler
-  (e -> Eff es a) ->
-  (forall ex. Exception e ex -> Eff (ex :& es) a) ->
+  (exn -> Eff es a) ->
+  (forall e. Exception exn e -> Eff (e :& es) a) ->
   Eff es a
 handle h f =
   try f >>= \case
@@ -383,10 +383,10 @@
     Right a -> pure a
 
 catch ::
-  forall e (es :: Effects) a.
-  (forall ex. Exception e ex -> Eff (ex :& es) a) ->
+  forall exn (es :: Effects) a.
+  (forall e. Exception exn e -> Eff (e :& es) a) ->
   -- | If the exception is thrown, apply this handler
-  (e -> Eff es a) ->
+  (exn -> Eff es a) ->
   Eff es a
 catch f h = handle h f
 
@@ -395,13 +395,38 @@
 -- exception.  This is essentially the same as
 -- @Control.Exception.'Control.Exception.bracket'@, whose
 -- documentation you can inspect for further details.
+--
+-- @bracket@ has a very general type that does not require @es@ to
+-- contain an exception or IO effect. The reason that this is safe is:
+--
+--    * While @bracket@ does catch exceptions, this is unobservable,
+--      since the exception is re-thrown; the cleanup action happens
+--      unconditionally; and no part of it gets access to the thrown
+--      exception.
+--
+--    * 'Eff' itself is able to guarantee that any exceptions thrown
+--      in the body will be actually thrown before @bracket@
+--      exits. This is inherited from the fact that @Eff@ is a wrapper
+--      around 'IO'.
+--
+-- While it is usually the case that the cleanup action will in fact
+-- want to use @IO@ effects, this is not universally true, see the
+-- @polymorphicBracket@ example for an example.
 bracket ::
+  -- | Acquire the resource
   Eff es a ->
+  -- | Release the resource
   (a -> Eff es ()) ->
+  -- | Run the body
   (a -> Eff es b) ->
+  -- |
   Eff es b
-bracket before after body = UnsafeMkEff $ Control.Exception.bracket
-  (unsafeUnEff before) (unsafeUnEff . after) (unsafeUnEff . body)
+bracket before after body =
+  UnsafeMkEff $
+    Control.Exception.bracket
+      (unsafeUnEff before)
+      (unsafeUnEff . after)
+      (unsafeUnEff . body)
 
 -- |
 -- @
@@ -411,8 +436,8 @@
 -- (20,10)
 -- @
 get ::
-  (st :> es) =>
-  State s st ->
+  (e :> es) =>
+  State s e ->
   -- | The current value of the state
   Eff es s
 get (UnsafeMkState r) = UnsafeMkEff (readIORef r)
@@ -425,8 +450,8 @@
 -- ((), 30)
 -- @
 put ::
-  (st :> es) =>
-  State s st ->
+  (e :> es) =>
+  State s e ->
   -- | The new value of the state.  The new value is forced before
   -- writing it to the state.
   s ->
@@ -440,8 +465,8 @@
 -- ((), 20)
 -- @
 modify ::
-  (st :> es) =>
-  State s st ->
+  (e :> es) =>
+  State s e ->
   -- | Apply this function to the state.  The new value of the state
   -- is forced before writing it to the state.
   (s -> s) ->
@@ -523,7 +548,7 @@
   -- | Initial state
   s ->
   -- | Stateful computation
-  (forall st. State s st -> Eff (st :& es) a) ->
+  (forall e. State s e -> Eff (e :& es) a) ->
   -- | Result and final state
   Eff es (a, s)
 runState s f = do
@@ -644,7 +669,7 @@
 -- "Returned early with 5"
 -- @
 withEarlyReturn ::
-  (forall er. EarlyReturn r er -> Eff (er :& es) r) ->
+  (forall e. EarlyReturn r e -> Eff (e :& es) r) ->
   -- | ͘
   Eff es r
 withEarlyReturn = handle pure
@@ -659,8 +684,8 @@
 -- "Returned early with 5"
 -- @
 returnEarly ::
-  (er :> es) =>
-  EarlyReturn r er ->
+  (e :> es) =>
+  EarlyReturn r e ->
   -- | Return early to the handler, with this value.
   r ->
   Eff es a
@@ -677,7 +702,7 @@
   -- | Initial state
   s ->
   -- | Stateful computation
-  (forall st. State s st -> Eff (st :& es) a) ->
+  (forall e. State s e -> Eff (e :& es) a) ->
   -- | Result
   Eff es a
 evalState s f = fmap fst (runState s f)
@@ -779,7 +804,7 @@
 
 -- |
 -- @
--- >>> runPureEff $ withYieldToList $ \y -> do
+-- >>> runPureEff $ withYieldToList $ \\y -> do
 --   yield y 1
 --   yield y 2
 --   yield y 100
@@ -868,7 +893,7 @@
 -- 15
 -- @
 withJump ::
-  (forall j. Jump j -> Eff (j :& es) ()) ->
+  (forall e. Jump e -> Eff (e :& es) ()) ->
   -- | ͘
   Eff es ()
 withJump = withEarlyReturn
@@ -889,13 +914,13 @@
 -- 15
 -- @
 jumpTo ::
-  (j :> es) =>
-  Jump j ->
+  (e :> es) =>
+  Jump e ->
   -- | ͘
   Eff es a
 jumpTo tag = throw tag ()
 
-unwrap :: (j :> es) => Jump j -> Maybe a -> Eff es a
+unwrap :: (e :> es) => Jump e -> Maybe a -> Eff es a
 unwrap j = \case
   Nothing -> jumpTo j
   Just a -> pure a
diff --git a/src/Bluefin/Internal/Examples.hs b/src/Bluefin/Internal/Examples.hs
--- a/src/Bluefin/Internal/Examples.hs
+++ b/src/Bluefin/Internal/Examples.hs
@@ -616,3 +616,33 @@
           applicationState = mapHandle a,
           logger = mapHandle l
         }
+
+-- This example shows a case where we can use @bracket@ polymorphically
+-- in order to perform correct cleanup if @es@ is instantiated to a
+-- set of effects that includes exceptions.
+polymorphicBracket ::
+  (st :> es) =>
+  State (Integer, Bool) st ->
+  Eff es () ->
+  Eff es ()
+polymorphicBracket st act =
+  bracket
+    (pure ())
+    -- Always set the boolean indicating that we have terminated
+    (\_ -> modify st (\(c, b) -> (c, True)))
+    -- Perform the given effectful action, then increment the counter
+    (\_ -> do act; modify st (\(c, b) -> ((c + 1), b)))
+
+-- Results in (1, True)
+polymorphicBracketExample1 :: (Integer, Bool)
+polymorphicBracketExample1 =
+  runPureEff $ do
+    (_res, st) <- runState (0, False) $ \st -> polymorphicBracket st (pure ())
+    pure st
+
+-- Results in (0, True)
+polymorphicBracketExample2 :: (Integer, Bool)
+polymorphicBracketExample2 =
+  runPureEff $ do
+    (_res, st) <- runState (0, False) $ \st -> try $ \e -> polymorphicBracket st (throw e 42)
+    pure st
