diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # recursion
 
+## 2.2.3.0
+
+* Add `hypo`
+* Add generic implementations of `project` and `embed`, following
+  [recursion-schemes](hackage.haskell.org/package/recursion-schemes-5.1.1.1/changelog)
+
 ## 2.2.2.0
 
 * Add `cotransverse` for parity with `recursion-schemes >= 5.1.1`
diff --git a/cabal.project b/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal.project
@@ -0,0 +1,2 @@
+packages: ./
+constraints: recursion +development
diff --git a/cabal.project.local b/cabal.project.local
deleted file mode 100644
--- a/cabal.project.local
+++ /dev/null
@@ -1,1 +0,0 @@
-constraints: yayo +development
diff --git a/recursion.cabal b/recursion.cabal
--- a/recursion.cabal
+++ b/recursion.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.18
 name: recursion
-version: 2.2.2.0
+version: 2.2.3.0
 license: BSD3
 license-file: LICENSE
 copyright: Copyright: (c) 2018-2019 Vanessa McHale
@@ -13,7 +13,7 @@
 category: Control, Recursion
 build-type: Simple
 extra-source-files:
-    cabal.project.local
+    cabal.project
 extra-doc-files: README.md
                  CHANGELOG.md
 
@@ -34,18 +34,19 @@
     default-language: Haskell2010
     other-extensions: DeriveFunctor FlexibleContexts
                       ExistentialQuantification RankNTypes TypeFamilies DeriveFoldable
-                      DeriveTraversable
+                      DeriveTraversable DefaultSignatures TypeOperators
+                      MultiParamTypeClasses
     ghc-options: -Wall
     build-depends:
         base >=4.9 && <5,
         composition-prelude -any
-
+    
     if flag(development)
         ghc-options: -Werror
-
+    
     if impl(ghc >=8.0)
         ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates
                      -Wredundant-constraints -Wnoncanonical-monad-instances
-
+    
     if impl(ghc >=8.4)
         ghc-options: -Wmissing-export-lists
diff --git a/src/Control/Recursion.hs b/src/Control/Recursion.hs
--- a/src/Control/Recursion.hs
+++ b/src/Control/Recursion.hs
@@ -1,10 +1,13 @@
+{-# LANGUAGE DefaultSignatures         #-}
 {-# LANGUAGE DeriveFoldable            #-}
 {-# LANGUAGE DeriveFunctor             #-}
 {-# LANGUAGE DeriveTraversable         #-}
 {-# LANGUAGE ExistentialQuantification #-}
 {-# LANGUAGE FlexibleContexts          #-}
+{-# LANGUAGE MultiParamTypeClasses     #-}
 {-# LANGUAGE RankNTypes                #-}
 {-# LANGUAGE TypeFamilies              #-}
+{-# LANGUAGE TypeOperators             #-}
 
 module Control.Recursion
     ( -- * Typeclasses
@@ -25,6 +28,7 @@
     , zygo
     , para
     , apo
+    , hypo
     , elgot
     , coelgot
     , micro
@@ -66,6 +70,7 @@
 import           Data.List.NonEmpty  (NonEmpty (..))
 import qualified Data.List.NonEmpty  as NE
 import           Data.Traversable    (Traversable (..))
+import           GHC.Generics
 import           Numeric.Natural     (Natural)
 
 type family Base t :: * -> *
@@ -74,10 +79,16 @@
 
     project :: t -> Base t t
 
+    default project :: (Generic t, Generic (Base t t), HCoerce (Rep t) (Rep (Base t t))) => t -> Base t t
+    project = to . hcoerce . from
+
 class (Functor (Base t)) => Corecursive t where
 
     embed :: Base t t -> t
 
+    default embed :: (Generic t, Generic (Base t t), HCoerce (Rep (Base t t)) (Rep t)) => Base t t -> t
+    embed = to . hcoerce . from
+
 -- | Base functor for a list of type @[a]@.
 data ListF a b = Cons a b
                | Nil
@@ -291,6 +302,12 @@
 apo :: (Corecursive t) => (a -> Base t (Either t a)) -> a -> t
 apo g = a where a = embed . fmap (either id a) . g
 
+-- | Hypomorphism.
+--
+-- @since 2.2.3.0
+hypo :: (Recursive t, Corecursive t) => (a -> Base t (Either t a)) -> (Base t (t, b) -> b) -> a -> b
+hypo φ ψ = para ψ . apo φ
+
 -- | Should satisfy:
 --
 -- @
@@ -331,3 +348,26 @@
 
 refix :: (Recursive s, Corecursive t, Base s ~ Base t) => s -> t
 refix = cata embed
+
+-- taken from http://hackage.haskell.org/package/recursion-schemes/docs/src/Data.Functor.Foldable.html#gcoerce
+class HCoerce f g where
+    hcoerce :: f a -> g a
+
+instance HCoerce f g => HCoerce (M1 i c f) (M1 i c' g) where
+    hcoerce (M1 x) = M1 (hcoerce x)
+
+instance HCoerce (K1 i c) (K1 j c) where
+    hcoerce = K1 . unK1
+
+instance HCoerce U1 U1 where
+    hcoerce = id
+
+instance HCoerce V1 V1 where
+    hcoerce = id
+
+instance (HCoerce f g, HCoerce f' g') => HCoerce (f :*: f') (g :*: g') where
+    hcoerce (x :*: y) = hcoerce x :*: hcoerce y
+
+instance (HCoerce f g, HCoerce f' g') => HCoerce (f :+: f') (g :+: g') where
+    hcoerce (L1 x) = L1 (hcoerce x)
+    hcoerce (R1 x) = R1 (hcoerce x)
