diff --git a/bowtie.cabal b/bowtie.cabal
--- a/bowtie.cabal
+++ b/bowtie.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.38.0.
+-- This file has been generated from package.yaml by hpack version 0.39.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           bowtie
-version:        0.7.0
+version:        0.8.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
@@ -73,11 +73,12 @@
     , bifunctors ==5.6.*
     , comonad ==5.0.*
     , dependent-map ==0.4.*
+    , hashable >=1.4 && <1.6
     , mtl ==2.3.*
     , nonempty-containers ==0.3.*
     , optics ==0.4.*
     , prettyprinter ==1.7.*
     , recursion-schemes ==5.2.*
     , semigroupoids ==6.0.*
-    , some ==1.0.*
+    , some ==1.1.*
   default-language: GHC2021
diff --git a/src/Bowtie/Anno.hs b/src/Bowtie/Anno.hs
--- a/src/Bowtie/Anno.hs
+++ b/src/Bowtie/Anno.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE DeriveAnyClass #-}
+
 module Bowtie.Anno
   ( Anno (..)
   , annoUnit
@@ -11,6 +13,8 @@
   )
 where
 
+import Data.Hashable (Hashable)
+import GHC.Generics (Generic)
 import Control.Comonad (Comonad (..))
 import Control.Exception (Exception)
 import Control.Monad.Reader (Reader, ReaderT (..), runReader)
@@ -27,7 +31,8 @@
 -- | An "annotation" with associated value.
 type Anno :: Type -> Type -> Type
 data Anno k v = Anno {annoKey :: !k, annoVal :: !v}
-  deriving stock (Eq, Ord, Show, Functor, Foldable, Traversable)
+  deriving stock (Eq, Ord, Show, Functor, Foldable, Traversable, Generic)
+  deriving anyclass (Hashable)
 
 instance Bifunctor Anno where
   bimap f g (Anno k v) = Anno (f k) (g v)
diff --git a/src/Bowtie/Jot.hs b/src/Bowtie/Jot.hs
--- a/src/Bowtie/Jot.hs
+++ b/src/Bowtie/Jot.hs
@@ -25,6 +25,7 @@
 import Data.Bifoldable (Bifoldable (..))
 import Data.Bifunctor (Bifunctor (..))
 import Data.Bitraversable (Bitraversable (..))
+import Data.Hashable (Hashable)
 import Data.Kind (Type)
 import Data.String (IsString (..))
 import Prettyprinter (Pretty (..))
@@ -32,7 +33,7 @@
 -- | The base functor for a 'Jot'
 newtype JotF g k a r = JotF {unJotF :: Anno k (g a r)}
   deriving stock (Show, Functor)
-  deriving newtype (Eq, Ord)
+  deriving newtype (Eq, Ord, Hashable)
 
 pattern JotFP :: k -> g a r -> JotF g k a r
 pattern JotFP k v = JotF (Anno k v)
@@ -72,6 +73,8 @@
 deriving newtype instance (Ord k, Ord (g a (Jot g k a))) => Ord (Jot g k a)
 
 deriving stock instance (Show k, Show (g a (Jot g k a))) => Show (Jot g k a)
+
+deriving newtype instance (Hashable k, Hashable (g a (Jot g k a))) => Hashable (Jot g k a)
 
 deriving newtype instance (Monoid k, IsString (g a (Jot g k a))) => IsString (Jot g k a)
 
diff --git a/src/Bowtie/Memo.hs b/src/Bowtie/Memo.hs
--- a/src/Bowtie/Memo.hs
+++ b/src/Bowtie/Memo.hs
@@ -24,6 +24,7 @@
 where
 
 import Bowtie.Anno (Anno (..), annoRight, annoRightM)
+import Data.Hashable (Hashable)
 import Bowtie.Fix (Fix)
 import Bowtie.Foldable (cataM)
 import Control.Monad.Reader (Reader, ReaderT (..), runReader)
@@ -36,7 +37,7 @@
 -- | The base functor for a 'Memo'
 newtype MemoF f k r = MemoF {unMemoF :: Anno k (f r)}
   deriving stock (Show, Functor, Foldable, Traversable)
-  deriving newtype (Eq, Ord)
+  deriving newtype (Eq, Ord, Hashable)
 
 pattern MemoFP :: k -> f r -> MemoF f k r
 pattern MemoFP k v = MemoF (Anno k v)
@@ -72,6 +73,8 @@
 deriving newtype instance (Eq k, Eq (f (Memo f k))) => Eq (Memo f k)
 
 deriving newtype instance (Ord k, Ord (f (Memo f k))) => Ord (Memo f k)
+
+deriving newtype instance (Hashable k, Hashable (f (Memo f k))) => Hashable (Memo f k)
 
 deriving stock instance (Show k, Show (f (Memo f k))) => Show (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
@@ -37,9 +37,11 @@
 import Data.Coerce (coerce)
 import Data.Dependent.Map (DMap)
 import Data.Dependent.Map qualified as DMap
+import Data.EqP (EqP (..))
 import Data.Functor.Identity (Identity (..))
 import Data.GADT.Compare (GCompare (..), GEq (..), GOrdering (..), defaultCompare, defaultEq)
 import Data.Kind (Type)
+import Data.OrdP (OrdP (..))
 import Data.Proxy (Proxy (..))
 import Data.Some (Some (..))
 import Data.Type.Bool (type (||))
@@ -59,6 +61,12 @@
   geq (Key ps1 _) (Key ps2 _) =
     fmap (\Refl -> Refl) (sameSymbol ps1 ps2)
 
+instance EqP (Key d) where
+  eqp (Key ps1 _) (Key ps2 _) =
+    case sameSymbol ps1 ps2 of
+      Just Refl -> True
+      Nothing -> False
+
 instance Eq (Key d v) where
   (==) = defaultEq
 
@@ -68,6 +76,13 @@
       LTI -> GLT
       EQI -> GEQ
       GTI -> GGT
+
+instance OrdP (Key d) where
+  comparep (Key ps1 _) (Key ps2 _) =
+    case cmpSymbol ps1 ps2 of
+      LTI -> LT
+      EQI -> EQ
+      GTI -> GT
 
 instance Ord (Key d v) where
   compare = defaultCompare
