diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# 0.4.0.0
+
+* Move `mapHandle` out of class `Handle` and remove `handleMapHandle`.
+  See `Bluefin.Compound` for instructions about migrating.
+
 # 0.2.7.0
 
 * Add `Bluefin.Compound.handleOneWayCoercible`
diff --git a/bluefin.cabal b/bluefin.cabal
--- a/bluefin.cabal
+++ b/bluefin.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               bluefin
-version:            0.2.7.0
+version:            0.4.0.0
 license:            MIT
 license-file:       LICENSE
 author:             Tom Ellis
@@ -42,6 +42,6 @@
       Bluefin.System.IO,
       Bluefin.Writer,
     build-depends:
-      bluefin-internal >= 0.3.5.0 && < 0.4
+      bluefin-internal >= 0.4.0.0 && < 0.5
     hs-source-dirs:   src
     default-language: Haskell2010
diff --git a/src/Bluefin/Compound.hs b/src/Bluefin/Compound.hs
--- a/src/Bluefin/Compound.hs
+++ b/src/Bluefin/Compound.hs
@@ -402,9 +402,14 @@
     --     counter7State :: 'Bluefin.State.State' Int e,
     --     counter7Stream :: 'Bluefin.Stream.Stream' String e
     --   }
+    --   deriving (Handle) via OneWayCoercibleHandle Counter7
     --
-    -- instance 'Handle' Counter7 where
-    --   handleImpl = handleMapHandle $ \\c ->
+    -- -- | The "forall" in the type of @incCounter7@ means that we
+    -- -- can't derive the @OneWayCoercible@ instance with
+    -- -- 'OneWayCoercible.gOneWayCoercible' so instead we use 'oneWayCoercibleTrustMe'.
+    --
+    -- instance (e :> es) => 'OneWayCoercible' (Counter7 e) (Counter7 es) where
+    --   oneWayCoercibleImpl = oneWayCoercibleTrustMe $ \\c ->
     --     MkCounter7
     --       { incCounter7Impl = \\ex -> 'useImplUnder' (incCounter7Impl c ex),
     --         counter7State = 'mapHandle' (counter7State c),
@@ -492,9 +497,17 @@
     --   { askLRImpl :: 'Bluefin.Eff.Eff' e r,
     --     localLRImpl :: forall e' a. (r -> r) -> Eff e' a -> Eff (e' :& e) a
     --   }
+    --   deriving (Handle) via OneWayCoercibleHandle (DynamicReader r)
     --
-    -- instance 'Handle' (DynamicReader r) where
-    --   mapHandle h =
+    -- -- | The "forall" in the type of @localRImpl@ means that we
+    -- -- can't derive the @OneWayCoercible@ instance with
+    -- -- 'OneWayCoercible.gOneWayCoercible' instead we use 'oneWayCoercibleTrustMe'.
+    --
+    -- instance
+    --   (e :> es) =>
+    --   OneWayCoercible (DynamicReader r e) (DynamicReader r es)
+    --   where
+    --   oneWayCoercibleImpl = oneWayCoercibleTrustMe $ \\h ->
     --     DynamicReader
     --       { askLRImpl = 'useImpl' (askLRImpl h),
     --         localLRImpl = \\f k -> useImplUnder (localLRImpl h f k)
@@ -653,9 +666,9 @@
     -- * Functions for making compound effects
 
     -- ** @Handle@
-    Handle (handleImpl, mapHandle),
+    Handle (handleImpl),
     HandleD,
-    handleMapHandle,
+    mapHandle,
 
     -- ** @OneWayCoercible@
 
@@ -664,6 +677,7 @@
     OneWayCoercible.OneWayCoercible (OneWayCoercible.oneWayCoercibleImpl),
     OneWayCoercibleHandle (MkOneWayCoercibleHandle),
     handleOneWayCoercible,
+    withHandle,
     OneWayCoercible.gOneWayCoercible,
     oneWayCoercibleTrustMe,
     -- | Bluefin re-exports @Generic@ for convenience.
