diff --git a/bowtie.cabal b/bowtie.cabal
--- a/bowtie.cabal
+++ b/bowtie.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           bowtie
-version:        0.5.0
+version:        0.6.0
 synopsis:       Tying knots in polynomial functors
 description:    Please see the README on GitHub at <https://github.com/ejconlon/bowtie#readme>
 homepage:       https://github.com/ejconlon/bowtie#readme
@@ -16,7 +16,7 @@
 license:        BSD3
 build-type:     Simple
 tested-with:
-    GHC == 9.6.4
+    GHC == 9.8.4
 extra-source-files:
     README.md
 
diff --git a/src/Bowtie/Foldable.hs b/src/Bowtie/Foldable.hs
--- a/src/Bowtie/Foldable.hs
+++ b/src/Bowtie/Foldable.hs
@@ -1,5 +1,6 @@
 module Bowtie.Foldable
-  ( Base1
+  ( cataM
+  , Base1
   , Recursive1 (..)
   , Corecursive1 (..)
   , cata1
@@ -14,7 +15,11 @@
 import Data.Bifoldable (Bifoldable (..))
 import Data.Bifunctor (Bifunctor (..))
 import Data.Bitraversable (Bitraversable (..))
+import Data.Functor.Foldable (Base, Recursive (..))
 import Data.Kind (Type)
+
+cataM :: (Monad m, Recursive t, Base t ~ f, Traversable f) => (f k -> m k) -> t -> m k
+cataM f = cata (sequence >=> f)
 
 -- | 'Base' for Bifunctors
 type family Base1 (f :: Type -> Type) :: Type -> Type -> Type
diff --git a/src/Bowtie/Memo.hs b/src/Bowtie/Memo.hs
--- a/src/Bowtie/Memo.hs
+++ b/src/Bowtie/Memo.hs
@@ -8,6 +8,7 @@
   , Memo (..)
   , pattern MemoP
   , mkMemo
+  , mkMemoM
   , reMkMemo
   , reMkMemoM
   , unMkMemo
@@ -26,6 +27,7 @@
 
 import Bowtie.Anno (Anno (..), annoRight, annoRightM)
 import Bowtie.Fix (Fix)
+import Bowtie.Foldable (cataM)
 import Control.Monad.Reader (Reader, ReaderT (..), runReader)
 import Data.Functor.Apply (Apply (..))
 import Data.Functor.Foldable (Base, Corecursive (..), Recursive (..))
@@ -98,6 +100,9 @@
 -- function to calculate a key for every level.
 mkMemo :: (Recursive t, Base t ~ f) => (f k -> k) -> t -> Memo f k
 mkMemo f = cata (\v -> MemoP (f (fmap memoKey v)) v)
+
+mkMemoM :: (Monad m, Recursive t, Base t ~ f, Traversable f) => (f k -> m k) -> t -> m (Memo f k)
+mkMemoM f = cataM (\v -> fmap (`MemoP` v) (f (fmap memoKey v)))
 
 -- | Rebuild a memo with a new annotation.
 reMkMemo :: (Functor f) => (MemoF f j (Memo f k) -> k) -> Memo f j -> Memo f k
diff --git a/src/Bowtie/SMap.hs b/src/Bowtie/SMap.hs
--- a/src/Bowtie/SMap.hs
+++ b/src/Bowtie/SMap.hs
@@ -15,6 +15,7 @@
   , Member
   , NonMember
   , Inserted
+  , Without
   , Deleted
   , Reordered
   , SMap
@@ -88,13 +89,6 @@
 deleteDM :: (KnownSymbol s) => Proxy s -> DM d -> DM d
 deleteDM ps = DMap.delete (key ps)
 
--- type family BoolEqF (x :: Symbol) (y :: Symbol) :: Bool where
---   BoolEqF x x = True
---   BoolEqF x y = False
---
--- castBoolEq :: (BoolEqF x y == True) => x :~: y
--- castBoolEq = undefined
-
 type family MemberF (x :: Symbol) (xs :: [Symbol]) :: Bool where
   MemberF x '[] = False
   MemberF x (x : zs) = True
@@ -121,14 +115,22 @@
 
 instance (zs ~ InsertedF x (y : ys), Member x zs) => Inserted x (y : ys) zs
 
+type family WithoutF (x :: Symbol) (xs :: [Symbol]) :: [Symbol] where
+  WithoutF x '[] = '[]
+  WithoutF x (x : zs) = zs
+  WithoutF x (y : zs) = y : WithoutF x zs
+
+class (NonMember x zs) => Without (x :: Symbol) (xs :: [Symbol]) (zs :: [Symbol]) | x xs -> zs
+
+instance (zs ~ WithoutF x '[]) => Without x '[] zs
+
+instance (zs ~ WithoutF x (y : ys), NonMember x zs) => Without x (y : ys) zs
+
 type family DeletedF (x :: Symbol) (xs :: [Symbol]) :: [Symbol] where
-  DeletedF x '[] = '[]
   DeletedF x (x : zs) = zs
   DeletedF x (y : zs) = y : DeletedF x zs
 
 class (NonMember x zs) => Deleted (x :: Symbol) (xs :: [Symbol]) (zs :: [Symbol]) | x xs -> zs
-
-instance (zs ~ DeletedF x '[]) => Deleted x '[] zs
 
 instance (zs ~ DeletedF x (y : ys), NonMember x zs) => Deleted x (y : ys) zs
 
