diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.2.2.0
+
+* `Bluefin.Compound`: add `OneWayCoercible`, `OneWayCoercibleHandle`,
+  `gOneWayCoercible` and re-export `Generic`
+
 ## 0.2.1.0
 
 * `Bluefin.Compound`: Add `handleImpl`, `HandleD` and
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.1.0
+version:            0.2.2.0
 license:            MIT
 license-file:       LICENSE
 author:             Tom Ellis
@@ -39,6 +39,6 @@
       Bluefin.System.IO,
       Bluefin.Writer,
     build-depends:
-      bluefin-internal >= 0.2.1.0 && < 0.3
+      bluefin-internal >= 0.3.0.0 && < 0.4
     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
@@ -251,26 +251,24 @@
     -- @getCounter4@ were, they're just defined in the handler.  In
     -- order to be used polymorphically, the actually effectful
     -- functions we call, @incCounter5@ and @getCounter5@ are derived
-    -- from the record fields by applying 'makeOp'.
+    -- from the record fields.
     --
     -- @
     -- data Counter5 e = MkCounter5
-    --   { incCounter5Impl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) (),
-    --     getCounter5Impl :: forall e'. String -> Eff (e' :& e) Int
+    --   { incCounter5Impl :: 'Bluefin.Eff.Eff' e (),
+    --     getCounter5Impl :: String -> Eff e Int
     --   }
+    --   deriving (Generic)
+    --   deriving (Handle) via 'OneWayCoercibleHandle' Counter5
     --
-    -- instance 'Handle' Counter5 where
-    --   mapHandle c =
-    --     MkCounter5
-    --       { incCounter5Impl = 'useImplUnder' (incCounter5Impl c),
-    --         getCounter5Impl = \\msg -> useImplUnder (getCounter5Impl c msg)
-    --       }
+    -- instance (e :> es) => 'OneWayCoercible.OneWayCoercible' (Counter5 e) (Counter5 es) where
+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'
     --
     -- incCounter5 :: (e :> es) => Counter5 e -> Eff es ()
-    -- incCounter5 e = 'makeOp' (incCounter5Impl ('mapHandle' e))
+    -- incCounter5 e = incCounter5Impl ('mapHandle' e)
     --
     -- getCounter5 :: (e :> es) => Counter5 e -> String -> Eff es Int
-    -- getCounter5 e msg = makeOp (getCounter5Impl (mapHandle e) msg)
+    -- getCounter5 e msg = getCounter5Impl (mapHandle e) msg
     --
     -- runCounter5 ::
     --   (e1 :> es) =>
@@ -328,21 +326,18 @@
     --
     -- @
     -- data Counter6 e = MkCounter6
-    --   { incCounter6Impl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) (),
+    --   { incCounter6Impl :: 'Bluefin.Eff.Eff' e (),
     --     counter6State :: 'Bluefin.State.State' Int e,
     --     counter6Stream :: 'Bluefin.Stream.Stream' String e
     --   }
+    --   deriving (Generic)
+    --   deriving (Handle) via 'OneWayCoercibleHandle' Counter6
     --
-    -- instance 'Handle' Counter6 where
-    --   mapHandle c =
-    --     MkCounter6
-    --       { incCounter6Impl = 'useImplUnder' (incCounter6Impl c),
-    --         counter6State = 'mapHandle' (counter6State c),
-    --         counter6Stream = mapHandle (counter6Stream c)
-    --       }
+    -- instance (e :> es) => 'OneWayCoercible.OneWayCoercible' (Counter6 e) (Counter6 es) where
+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'
     --
     -- incCounter6 :: (e :> es) => Counter6 e -> Eff es ()
-    -- incCounter6 e = 'makeOp' (incCounter6Impl (mapHandle e))
+    -- incCounter6 e = incCounter6Impl (mapHandle e)
     --
     -- getCounter6 :: (e :> es) => Counter6 e -> String -> Eff es Int
     -- getCounter6 (MkCounter6 _ st y) msg = do
@@ -409,7 +404,7 @@
     --   }
     --
     -- instance 'Handle' Counter7 where
-    --   mapHandle c =
+    --   handleImpl = handleMapHandle $ \\c ->
     --     MkCounter7
     --       { incCounter7Impl = \\ex -> 'useImplUnder' (incCounter7Impl c ex),
     --         counter7State = 'mapHandle' (counter7State c),
@@ -494,14 +489,14 @@
     --
     -- @
     -- data DynamicReader r e = DynamicReader
-    --   { askLRImpl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) r,
+    --   { askLRImpl :: 'Bluefin.Eff.Eff' e r,
     --     localLRImpl :: forall e' a. (r -> r) -> Eff e' a -> Eff (e' :& e) a
     --   }
     --
     -- instance 'Handle' (DynamicReader r) where
     --   mapHandle h =
     --     DynamicReader
-    --       { askLRImpl = 'useImplUnder' (askLRImpl h),
+    --       { askLRImpl = 'useImpl' (askLRImpl h),
     --         localLRImpl = \\f k -> useImplUnder (localLRImpl h f k)
     --       }
     --
@@ -543,22 +538,21 @@
     --
     -- @
     -- data FileSystem es = MkFileSystem
-    --   { readFileImpl :: forall e. FilePath -> 'Bluefin.Eff.Eff' (e :& es) String,
-    --     writeFileImpl :: forall e. FilePath -> String -> Eff (e :& es) ()
+    --   { readFileImpl :: FilePath -> 'Bluefin.Eff.Eff' es String,
+    --     writeFileImpl :: FilePath -> String -> Eff es ()
     --   }
+    --   deriving (Generic)
+    --   deriving (Handle) via 'OneWayCoercibleHandle' FileSystem
     --
-    -- instance 'Handle' FileSystem where
-    --   mapHandle fs = MkFileSystem {
-    --     readFileImpl = \\fp -> 'useImplUnder' (readFileImpl fs fp),
-    --     writeFileImpl = \\fp s -> useImplUnder (writeFileImpl fs fp s)
-    --     }
+    -- instance (e :> es) => 'OneWayCoercible.OneWayCoercible' (FileSystem e) (FileSystem es) where
+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'
     --
     -- readFile :: (e :> es) => FileSystem e -> FilePath -> Eff es String
-    -- readFile fs filepath = 'makeOp' (readFileImpl ('mapHandle' fs) filepath)
+    -- readFile fs filepath = readFileImpl ('mapHandle' fs) filepath
     --
     -- writeFile :: (e :> es) => FileSystem e -> FilePath -> String -> Eff es ()
     -- writeFile fs filepath contents =
-    --   makeOp (writeFileImpl (mapHandle fs) filepath contents)
+    --   writeFileImpl (mapHandle fs) filepath contents
     -- @
     --
     -- We can make a pure handler that simulates reading and writing
@@ -663,6 +657,15 @@
     HandleD,
     handleMapHandle,
 
+    -- ** @OneWayCoercible@
+
+    -- | The documentation for 'Handle' shows how to use
+    -- @OneWayCoercible@ to define @Handle@ instances.
+    OneWayCoercible.OneWayCoercible,
+    OneWayCoercibleHandle,
+    OneWayCoercible.gOneWayCoercible,
+    OneWayCoercible.Generic,
+
     -- ** Other functions for compound effects
     makeOp,
     useImpl,
@@ -680,3 +683,4 @@
 where
 
 import Bluefin.Internal
+import qualified Bluefin.Internal.OneWayCoercible as OneWayCoercible
