diff --git a/int-like.cabal b/int-like.cabal
--- a/int-like.cabal
+++ b/int-like.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.37.0.
+-- This file has been generated from package.yaml by hpack version 0.38.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           int-like
-version:        0.1.4
+version:        0.2.0
 synopsis:       Newtype wrappers over IntSet and IntMap
 description:    Please see the README on GitHub at <https://github.com/ejconlon/int-like#readme>
 category:       Data Structures
@@ -53,7 +53,9 @@
       LambdaCase
       KindSignatures
       MultiParamTypeClasses
+      QuantifiedConstraints
       Rank2Types
+      RoleAnnotations
       ScopedTypeVariables
       StandaloneDeriving
       TemplateHaskell
@@ -63,9 +65,9 @@
       TypeFamilies
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints -fno-warn-unused-top-binds -fwrite-ide-info -hiedir=.hie
   build-depends:
-      algebraic-graphs ==0.7.*
+      algebraic-graphs >=0.7 && <0.9
     , base >=4.12 && <5
-    , containers ==0.6.*
+    , containers >=0.6 && <0.9
     , deepseq >=1.4 && <1.6
-    , hashable >=1.3 && <1.5
+    , hashable >=1.3 && <1.6
   default-language: Haskell2010
diff --git a/src/IntLike/Graph.hs b/src/IntLike/Graph.hs
--- a/src/IntLike/Graph.hs
+++ b/src/IntLike/Graph.hs
@@ -26,10 +26,12 @@
 import IntLike.Set (IntLikeSet (..))
 import qualified IntLike.Set as ILS
 
+type role IntLikeGraph nominal
+
 newtype IntLikeGraph x = IntLikeGraph {unIntLikeGraph :: AdjacencyIntMap}
   deriving newtype (Eq, Ord, Show, NFData)
 
-instance Coercible x Int => Graph (IntLikeGraph x) where
+instance (Coercible x Int) => Graph (IntLikeGraph x) where
   type Vertex (IntLikeGraph x) = x
   empty = IntLikeGraph AdjacencyIntMap.empty
   vertex v = IntLikeGraph (AdjacencyIntMap.vertex (coerce v))
@@ -40,19 +42,19 @@
 adjacencyIntMultiMap = coerce . AdjacencyIntMap.adjacencyIntMap . unIntLikeGraph
 {-# INLINE adjacencyIntMultiMap #-}
 
-vertexList :: Coercible x Int => IntLikeGraph x -> [x]
+vertexList :: (Coercible x Int) => IntLikeGraph x -> [x]
 vertexList = coerce . AdjacencyIntMap.vertexList . unIntLikeGraph
 {-# INLINE vertexList #-}
 
-fromDirectedEdges :: Coercible x Int => [(x, x)] -> IntLikeGraph x
+fromDirectedEdges :: (Coercible x Int) => [(x, x)] -> IntLikeGraph x
 fromDirectedEdges = IntLikeGraph . AdjacencyIntMap.edges . coerce
 {-# INLINE fromDirectedEdges #-}
 
-fromUndirectedEdges :: Coercible x Int => [(x, x)] -> IntLikeGraph x
+fromUndirectedEdges :: (Coercible x Int) => [(x, x)] -> IntLikeGraph x
 fromUndirectedEdges es = overlay (fromDirectedEdges es) (fromDirectedEdges (fmap swap es))
 {-# INLINE fromUndirectedEdges #-}
 
-reachable :: Coercible x Int => x -> IntLikeGraph x -> [x]
+reachable :: (Coercible x Int) => x -> IntLikeGraph x -> [x]
 reachable x = coerce . flip AIMA.reachable (coerce x) . unIntLikeGraph
 {-# INLINE reachable #-}
 
@@ -60,7 +62,7 @@
   deriving stock (Show)
   deriving newtype (Eq, Ord, Enum, Hashable, NFData)
 
-undirectedComponents :: Coercible x Int => [(x, x)] -> IntLikeEquiv Component x
+undirectedComponents :: (Coercible x Int) => [(x, x)] -> IntLikeEquiv Component x
 undirectedComponents es = go 0 startVs ILE.empty
  where
   g = fromUndirectedEdges es
diff --git a/src/IntLike/Map.hs b/src/IntLike/Map.hs
--- a/src/IntLike/Map.hs
+++ b/src/IntLike/Map.hs
@@ -1,29 +1,181 @@
+{-# LANGUAGE CPP #-}
+
 module IntLike.Map
-  ( IntLikeMap (..)
+  ( -- * Map type
+    IntLikeMap (..)
+
+    -- * Construction
   , empty
   , singleton
+  , fromSet
+
+    -- ** From Unordered Lists
   , fromList
-  , size
-  , null
-  , member
-  , toList
-  , keys
-  , keysSet
-  , elems
-  , lookup
-  , partialLookup
-  , findWithDefault
+  , fromListWith
+  , fromListWithKey
+
+    -- ** From Ascending Lists
+  , fromAscList
+  , fromAscListWith
+  , fromAscListWithKey
+  , fromDistinctAscList
+
+    -- * Insertion
   , insert
   , insertWith
+  , insertWithKey
+  , insertLookupWithKey
+
+    -- * Deletion\/Update
+  , delete
   , adjust
+  , adjustWithKey
+  , update
+  , updateWithKey
+  , updateLookupWithKey
   , alter
-  , delete
-  , minViewWithKey
+  , alterF
+
+    -- * Query
+
+    -- ** Lookup
+  , lookup
+  , (!?)
+  , (!)
+  , findWithDefault
+  , member
+  , notMember
+  , lookupLT
+  , lookupGT
+  , lookupLE
+  , lookupGE
+
+    -- ** Size
+  , null
+  , size
+
+    -- * Combine
+
+    -- ** Union
+  , union
+  , unionWith
+  , unionWithKey
+  , unions
+  , unionsWith
+
+    -- ** Difference
+  , difference
+  , (\\)
+  , differenceWith
+  , differenceWithKey
+
+    -- ** Intersection
+  , intersection
+  , intersectionWith
+  , intersectionWithKey
+
+    -- ** Symmetric difference
+#if MIN_VERSION_containers(0,8,0)
+  , symmetricDifference
+#endif
+
+    -- ** Disjoint
+  , disjoint
+
+    -- ** Compose
+  , compose
+
+    -- ** Universal combining function
+  , mergeWithKey
+
+    -- * Traversal
+
+    -- ** Map
+  , map
+  , mapWithKey
+  , traverseWithKey
+  , traverseMaybeWithKey
+  , mapAccum
+  , mapAccumWithKey
+  , mapAccumRWithKey
+  , mapKeys
+  , mapKeysWith
+  , mapKeysMonotonic
+
+    -- * Folds
+  , foldr
+  , foldl
+  , foldrWithKey
+  , foldlWithKey
+  , foldMapWithKey
+
+    -- ** Strict folds
+  , foldr'
+  , foldl'
+  , foldrWithKey'
+  , foldlWithKey'
+
+    -- * Conversion
+  , elems
+  , keys
+  , assocs
+  , keysSet
+
+    -- ** Lists
+  , toList
+
+    -- ** Ordered lists
+  , toAscList
+  , toDescList
+
+    -- * Filter
   , filter
+#if MIN_VERSION_containers(0,8,0)
+  , filterKeys
+#endif
+  , filterWithKey
   , restrictKeys
-  , map
+  , withoutKeys
+  , partition
+  , partitionWithKey
+  , takeWhileAntitone
+  , dropWhileAntitone
+  , spanAntitone
+  , mapMaybe
+  , mapMaybeWithKey
+  , mapEither
+  , mapEitherWithKey
+  , split
+  , splitLookup
+  , splitRoot
+
+    -- * Submap
+  , isSubmapOf
+  , isSubmapOfBy
+  , isProperSubmapOf
+  , isProperSubmapOfBy
+
+    -- * Min\/Max
+  , lookupMin
+  , lookupMax
+  , findMin
+  , findMax
+  , deleteMin
+  , deleteMax
+  , deleteFindMin
+  , deleteFindMax
+  , updateMin
+  , updateMax
+  , updateMinWithKey
+  , updateMaxWithKey
+  , minView
+  , maxView
+  , minViewWithKey
+  , maxViewWithKey
+
+    -- * Extra
+  , partialLookup
   , insertState
-  , mapWithKey
   )
 where
 
@@ -32,104 +184,528 @@
 import Data.IntMap.Strict (IntMap)
 import qualified Data.IntMap.Strict as IntMap
 import IntLike.Set (IntLikeSet (..))
-import Prelude hiding (filter, lookup, map, null)
+import Prelude hiding (filter, foldl, foldr, lookup, map, null)
 
+type role IntLikeMap nominal representational
+
 newtype IntLikeMap x a = IntLikeMap {unIntLikeMap :: IntMap a}
   deriving stock (Show, Traversable)
   deriving newtype (Eq, Ord, Functor, Foldable, NFData, Semigroup, Monoid)
 
-empty :: IntLikeMap x a
-empty = IntLikeMap IntMap.empty
+empty :: forall x a. IntLikeMap x a
+empty = coerce (IntMap.empty @a)
 {-# INLINE empty #-}
 
-singleton :: Coercible x Int => x -> a -> IntLikeMap x a
-singleton x = IntLikeMap . IntMap.singleton (coerce x)
+singleton :: forall x a. (Coercible x Int) => x -> a -> IntLikeMap x a
+singleton = coerce (IntMap.singleton @a)
 {-# INLINE singleton #-}
 
-fromList :: Coercible x Int => [(x, a)] -> IntLikeMap x a
-fromList = IntLikeMap . IntMap.fromList . coerce
+fromSet :: forall x a. (Coercible x Int) => (x -> a) -> IntLikeSet x -> IntLikeMap x a
+fromSet = coerce (IntMap.fromSet @a)
+{-# INLINE fromSet #-}
+
+fromList :: forall x a. (Coercible x Int) => [(x, a)] -> IntLikeMap x a
+fromList = coerce (IntMap.fromList @a)
 {-# INLINE fromList #-}
 
-size :: IntLikeMap x a -> Int
-size = IntMap.size . unIntLikeMap
-{-# INLINE size #-}
+fromListWith :: forall x a. (Coercible x Int) => (a -> a -> a) -> [(x, a)] -> IntLikeMap x a
+fromListWith = coerce (IntMap.fromListWith @a)
+{-# INLINE fromListWith #-}
 
-null :: IntLikeMap x a -> Bool
-null = IntMap.null . unIntLikeMap
-{-# INLINE null #-}
+fromListWithKey :: forall x a. (Coercible x Int) => (x -> a -> a -> a) -> [(x, a)] -> IntLikeMap x a
+fromListWithKey = coerce (IntMap.fromListWithKey @a)
+{-# INLINE fromListWithKey #-}
 
-member :: Coercible x Int => x -> IntLikeMap x a -> Bool
-member x = IntMap.member (coerce x) . unIntLikeMap
-{-# INLINE member #-}
+fromAscList :: forall x a. (Coercible x Int) => [(x, a)] -> IntLikeMap x a
+fromAscList = coerce (IntMap.fromAscList @a)
+{-# INLINE fromAscList #-}
 
-toList :: Coercible x Int => IntLikeMap x a -> [(x, a)]
-toList = coerce . IntMap.toList . unIntLikeMap
-{-# INLINE toList #-}
+fromAscListWith :: forall x a. (Coercible x Int) => (a -> a -> a) -> [(x, a)] -> IntLikeMap x a
+fromAscListWith = coerce (IntMap.fromAscListWith @a)
+{-# INLINE fromAscListWith #-}
 
-keys :: Coercible x Int => IntLikeMap x a -> [x]
-keys = coerce . IntMap.keys . unIntLikeMap
-{-# INLINE keys #-}
+fromAscListWithKey :: forall x a. (Coercible x Int) => (x -> a -> a -> a) -> [(x, a)] -> IntLikeMap x a
+fromAscListWithKey = coerce (IntMap.fromAscListWithKey @a)
+{-# INLINE fromAscListWithKey #-}
 
-keysSet :: IntLikeMap x a -> IntLikeSet x
-keysSet = IntLikeSet . IntMap.keysSet . unIntLikeMap
-{-# INLINE keysSet #-}
+fromDistinctAscList :: forall x a. (Coercible x Int) => [(x, a)] -> IntLikeMap x a
+fromDistinctAscList = coerce (IntMap.fromDistinctAscList @a)
+{-# INLINE fromDistinctAscList #-}
 
-elems :: IntLikeMap x a -> [a]
-elems = IntMap.elems . unIntLikeMap
-{-# INLINE elems #-}
+insert :: forall x a. (Coercible x Int) => x -> a -> IntLikeMap x a -> IntLikeMap x a
+insert = coerce (IntMap.insert @a)
+{-# INLINE insert #-}
 
-lookup :: Coercible x Int => x -> IntLikeMap x a -> Maybe a
-lookup x = IntMap.lookup (coerce x) . unIntLikeMap
+insertWith :: forall x a. (Coercible x Int) => (a -> a -> a) -> x -> a -> IntLikeMap x a -> IntLikeMap x a
+insertWith = coerce (IntMap.insertWith @a)
+{-# INLINE insertWith #-}
+
+insertWithKey :: forall x a. (Coercible x Int) => (x -> a -> a -> a) -> x -> a -> IntLikeMap x a -> IntLikeMap x a
+insertWithKey = coerce (IntMap.insertWithKey @a)
+{-# INLINE insertWithKey #-}
+
+insertLookupWithKey
+  :: forall x a. (Coercible x Int) => (x -> a -> a -> a) -> x -> a -> IntLikeMap x a -> (Maybe a, IntLikeMap x a)
+insertLookupWithKey = coerce (IntMap.insertLookupWithKey @a)
+{-# INLINE insertLookupWithKey #-}
+
+delete :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> IntLikeMap x a
+delete = coerce (IntMap.delete @a)
+{-# INLINE delete #-}
+
+adjust :: forall x a. (Coercible x Int) => (a -> a) -> x -> IntLikeMap x a -> IntLikeMap x a
+adjust = coerce (IntMap.adjust @a)
+{-# INLINE adjust #-}
+
+adjustWithKey :: forall x a. (Coercible x Int) => (x -> a -> a) -> x -> IntLikeMap x a -> IntLikeMap x a
+adjustWithKey = coerce (IntMap.adjustWithKey @a)
+{-# INLINE adjustWithKey #-}
+
+update :: forall x a. (Coercible x Int) => (a -> Maybe a) -> x -> IntLikeMap x a -> IntLikeMap x a
+update = coerce (IntMap.update @a)
+{-# INLINE update #-}
+
+updateWithKey :: forall x a. (Coercible x Int) => (x -> a -> Maybe a) -> x -> IntLikeMap x a -> IntLikeMap x a
+updateWithKey = coerce (IntMap.updateWithKey @a)
+{-# INLINE updateWithKey #-}
+
+updateLookupWithKey
+  :: forall x a. (Coercible x Int) => (x -> a -> Maybe a) -> x -> IntLikeMap x a -> (Maybe a, IntLikeMap x a)
+updateLookupWithKey = coerce (IntMap.updateLookupWithKey @a)
+{-# INLINE updateLookupWithKey #-}
+
+alter :: forall x a. (Coercible x Int) => (Maybe a -> Maybe a) -> x -> IntLikeMap x a -> IntLikeMap x a
+alter = coerce (IntMap.alter @a)
+{-# INLINE alter #-}
+
+alterF
+  :: forall x f a
+   . (Coercible x Int)
+  => (forall v u. (Coercible v u) => Coercible (f v) (f u))
+  => (Functor f)
+  => (Maybe a -> f (Maybe a))
+  -> x
+  -> IntLikeMap x a
+  -> f (IntLikeMap x a)
+alterF = coerce (IntMap.alterF @f @a)
+{-# INLINE alterF #-}
+
+lookup :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> Maybe a
+lookup = coerce (IntMap.lookup @a)
 {-# INLINE lookup #-}
 
-partialLookup :: Coercible x Int => x -> IntLikeMap x a -> a
-partialLookup x m = unIntLikeMap m IntMap.! coerce x
-{-# INLINE partialLookup #-}
+(!?) :: forall x a. (Coercible x Int) => IntLikeMap x a -> x -> Maybe a
+(!?) = coerce ((IntMap.!?) @a)
+{-# INLINE (!?) #-}
 
-findWithDefault :: Coercible x Int => a -> x -> IntLikeMap x a -> a
-findWithDefault a x = IntMap.findWithDefault a (coerce x) . unIntLikeMap
+(!) :: forall x a. (Coercible x Int) => IntLikeMap x a -> x -> a
+(!) = coerce ((IntMap.!) @a)
+{-# INLINE (!) #-}
+
+findWithDefault :: forall x a. (Coercible x Int) => a -> x -> IntLikeMap x a -> a
+findWithDefault = coerce (IntMap.findWithDefault @a)
 {-# INLINE findWithDefault #-}
 
-insert :: Coercible x Int => x -> a -> IntLikeMap x a -> IntLikeMap x a
-insert x a = IntLikeMap . IntMap.insert (coerce x) a . unIntLikeMap
-{-# INLINE insert #-}
+member :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> Bool
+member = coerce (IntMap.member @a)
+{-# INLINE member #-}
 
-insertWith :: Coercible x Int => (a -> a -> a) -> x -> a -> IntLikeMap x a -> IntLikeMap x a
-insertWith f x a = IntLikeMap . IntMap.insertWith f (coerce x) a . unIntLikeMap
-{-# INLINE insertWith #-}
+notMember :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> Bool
+notMember = coerce (IntMap.notMember @a)
+{-# INLINE notMember #-}
 
-adjust :: Coercible x Int => (a -> a) -> x -> IntLikeMap x a -> IntLikeMap x a
-adjust f x = IntLikeMap . IntMap.adjust f (coerce x) . unIntLikeMap
-{-# INLINE adjust #-}
+lookupLT :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> Maybe (x, a)
+lookupLT = coerce (IntMap.lookupLT @a)
+{-# INLINE lookupLT #-}
 
-alter :: Coercible x Int => (Maybe a -> Maybe a) -> x -> IntLikeMap x a -> IntLikeMap x a
-alter f x = IntLikeMap . IntMap.alter f (coerce x) . unIntLikeMap
-{-# INLINE alter #-}
+lookupGT :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> Maybe (x, a)
+lookupGT = coerce (IntMap.lookupGT @a)
+{-# INLINE lookupGT #-}
 
-delete :: Coercible x Int => x -> IntLikeMap x a -> IntLikeMap x a
-delete x = IntLikeMap . IntMap.delete (coerce x) . unIntLikeMap
-{-# INLINE delete #-}
+lookupLE :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> Maybe (x, a)
+lookupLE = coerce (IntMap.lookupLE @a)
+{-# INLINE lookupLE #-}
 
-minViewWithKey :: Coercible x Int => IntLikeMap x a -> Maybe ((x, a), IntLikeMap x a)
-minViewWithKey = coerce . IntMap.minViewWithKey . unIntLikeMap
-{-# INLINE minViewWithKey #-}
+lookupGE :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> Maybe (x, a)
+lookupGE = coerce (IntMap.lookupGE @a)
+{-# INLINE lookupGE #-}
 
-filter :: (a -> Bool) -> IntLikeMap x a -> IntLikeMap x a
-filter f = IntLikeMap . IntMap.filter f . unIntLikeMap
+null :: forall x a. IntLikeMap x a -> Bool
+null = coerce (IntMap.null @a)
+{-# INLINE null #-}
+
+size :: forall x a. IntLikeMap x a -> Int
+size = coerce (IntMap.size @a)
+{-# INLINE size #-}
+
+union :: forall x a. IntLikeMap x a -> IntLikeMap x a -> IntLikeMap x a
+union = coerce (IntMap.union @a)
+{-# INLINE union #-}
+
+unionWith :: forall x a. (a -> a -> a) -> IntLikeMap x a -> IntLikeMap x a -> IntLikeMap x a
+unionWith = coerce (IntMap.unionWith @a)
+{-# INLINE unionWith #-}
+
+unionWithKey
+  :: forall x a. (Coercible x Int) => (x -> a -> a -> a) -> IntLikeMap x a -> IntLikeMap x a -> IntLikeMap x a
+unionWithKey = coerce (IntMap.unionWithKey @a)
+{-# INLINE unionWithKey #-}
+
+unions
+  :: forall x f a
+   . (forall v u. (Coercible v u) => Coercible (f v) (f u))
+  => (Foldable f)
+  => f (IntLikeMap x a)
+  -> IntLikeMap x a
+unions = coerce (IntMap.unions @f @a)
+{-# INLINE unions #-}
+
+unionsWith
+  :: forall x f a
+   . (forall v u. (Coercible v u) => Coercible (f v) (f u))
+  => (Foldable f)
+  => (a -> a -> a)
+  -> f (IntLikeMap x a)
+  -> IntLikeMap x a
+unionsWith = coerce (IntMap.unionsWith @f @a)
+{-# INLINE unionsWith #-}
+
+difference :: forall x a b. IntLikeMap x a -> IntLikeMap x b -> IntLikeMap x a
+difference = coerce (IntMap.difference @a @b)
+{-# INLINE difference #-}
+
+(\\) :: forall x a b. IntLikeMap x a -> IntLikeMap x b -> IntLikeMap x a
+(\\) = coerce ((IntMap.\\) @a @b)
+{-# INLINE (\\) #-}
+
+differenceWith
+  :: forall x a b. (a -> b -> Maybe a) -> IntLikeMap x a -> IntLikeMap x b -> IntLikeMap x a
+differenceWith = coerce (IntMap.differenceWith @a @b)
+{-# INLINE differenceWith #-}
+
+differenceWithKey
+  :: forall x a b. (Coercible x Int) => (x -> a -> b -> Maybe a) -> IntLikeMap x a -> IntLikeMap x b -> IntLikeMap x a
+differenceWithKey = coerce (IntMap.differenceWithKey @a @b)
+{-# INLINE differenceWithKey #-}
+
+intersection :: forall x a b. IntLikeMap x a -> IntLikeMap x b -> IntLikeMap x a
+intersection = coerce (IntMap.intersection @a @b)
+{-# INLINE intersection #-}
+
+intersectionWith :: forall x a b c. (a -> b -> c) -> IntLikeMap x a -> IntLikeMap x b -> IntLikeMap x c
+intersectionWith = coerce (IntMap.intersectionWith @a @b @c)
+{-# INLINE intersectionWith #-}
+
+intersectionWithKey
+  :: forall x a b c. (Coercible x Int) => (x -> a -> b -> c) -> IntLikeMap x a -> IntLikeMap x b -> IntLikeMap x c
+intersectionWithKey = coerce (IntMap.intersectionWithKey @a @b @c)
+{-# INLINE intersectionWithKey #-}
+
+#if MIN_VERSION_containers(0,8,0)
+symmetricDifference :: forall x a. IntLikeMap x a -> IntLikeMap x a -> IntLikeMap x a
+symmetricDifference = coerce (IntMap.symmetricDifference @a)
+{-# INLINE symmetricDifference #-}
+#endif
+
+disjoint :: forall x a b. IntLikeMap x a -> IntLikeMap x b -> Bool
+disjoint = coerce (IntMap.disjoint @a @b)
+{-# INLINE disjoint #-}
+
+compose :: forall x c. IntLikeMap x c -> IntMap Int -> IntLikeMap x c
+compose = coerce (IntMap.compose @c)
+{-# INLINE compose #-}
+
+mergeWithKey
+  :: forall x a b c
+   . (Coercible x Int)
+  => (x -> a -> b -> Maybe c)
+  -> (IntLikeMap x a -> IntLikeMap x c)
+  -> (IntLikeMap x b -> IntLikeMap x c)
+  -> IntLikeMap x a
+  -> IntLikeMap x b
+  -> IntLikeMap x c
+mergeWithKey = coerce (IntMap.mergeWithKey @a @b @c)
+{-# INLINE mergeWithKey #-}
+
+map :: forall x a b. (a -> b) -> IntLikeMap x a -> IntLikeMap x b
+map = coerce (IntMap.map @a @b)
+{-# INLINE map #-}
+
+mapWithKey :: forall x a b. (Coercible x Int) => (x -> a -> b) -> IntLikeMap x a -> IntLikeMap x b
+mapWithKey = coerce (IntMap.mapWithKey @a @b)
+{-# INLINE mapWithKey #-}
+
+traverseWithKey
+  :: forall x t a b
+   . (Coercible x Int)
+  => (forall v u. (Coercible v u) => Coercible (t v) (t u))
+  => (Applicative t)
+  => (x -> a -> t b)
+  -> IntLikeMap x a
+  -> t (IntLikeMap x b)
+traverseWithKey = coerce (IntMap.traverseWithKey @t @a @b)
+{-# INLINE traverseWithKey #-}
+
+traverseMaybeWithKey
+  :: forall x f a b
+   . (Coercible x Int)
+  => (forall v u. (Coercible v u) => Coercible (f v) (f u))
+  => (Applicative f)
+  => (x -> a -> f (Maybe b))
+  -> IntLikeMap x a
+  -> f (IntLikeMap x b)
+traverseMaybeWithKey = coerce (IntMap.traverseMaybeWithKey @f @a @b)
+{-# INLINE traverseMaybeWithKey #-}
+
+mapAccum :: forall x a b c. (a -> b -> (a, c)) -> a -> IntLikeMap x b -> (a, IntLikeMap x c)
+mapAccum = coerce (IntMap.mapAccum @a @b @c)
+{-# INLINE mapAccum #-}
+
+mapAccumWithKey
+  :: forall x a b c. (Coercible x Int) => (a -> x -> b -> (a, c)) -> a -> IntLikeMap x b -> (a, IntLikeMap x c)
+mapAccumWithKey = coerce (IntMap.mapAccumWithKey @a @b @c)
+{-# INLINE mapAccumWithKey #-}
+
+mapAccumRWithKey
+  :: forall x a b c. (Coercible x Int) => (a -> x -> b -> (a, c)) -> a -> IntLikeMap x b -> (a, IntLikeMap x c)
+mapAccumRWithKey = coerce (IntMap.mapAccumRWithKey @a @b @c)
+{-# INLINE mapAccumRWithKey #-}
+
+mapKeys :: forall x a. (Coercible x Int) => (x -> x) -> IntLikeMap x a -> IntLikeMap x a
+mapKeys = coerce (IntMap.mapKeys @a)
+{-# INLINE mapKeys #-}
+
+mapKeysWith :: forall x a. (Coercible x Int) => (a -> a -> a) -> (x -> x) -> IntLikeMap x a -> IntLikeMap x a
+mapKeysWith = coerce (IntMap.mapKeysWith @a)
+{-# INLINE mapKeysWith #-}
+
+mapKeysMonotonic :: forall x a. (Coercible x Int) => (x -> x) -> IntLikeMap x a -> IntLikeMap x a
+mapKeysMonotonic = coerce (IntMap.mapKeysMonotonic @a)
+{-# INLINE mapKeysMonotonic #-}
+
+foldr :: forall x a b. (a -> b -> b) -> b -> IntLikeMap x a -> b
+foldr = coerce (IntMap.foldr @a @b)
+{-# INLINE foldr #-}
+
+foldl :: forall x a b. (a -> b -> a) -> a -> IntLikeMap x b -> a
+foldl = coerce (IntMap.foldl @a @b)
+{-# INLINE foldl #-}
+
+foldrWithKey :: forall x a b. (Coercible x Int) => (x -> a -> b -> b) -> b -> IntLikeMap x a -> b
+foldrWithKey = coerce (IntMap.foldrWithKey @a @b)
+{-# INLINE foldrWithKey #-}
+
+foldlWithKey :: forall x a b. (Coercible x Int) => (a -> x -> b -> a) -> a -> IntLikeMap x b -> a
+foldlWithKey = coerce (IntMap.foldlWithKey @a @b)
+{-# INLINE foldlWithKey #-}
+
+foldMapWithKey :: forall x m a. (Coercible x Int) => (Monoid m) => (x -> a -> m) -> IntLikeMap x a -> m
+foldMapWithKey = coerce (IntMap.foldMapWithKey @m @a)
+{-# INLINE foldMapWithKey #-}
+
+foldr' :: forall x a b. (a -> b -> b) -> b -> IntLikeMap x a -> b
+foldr' = coerce (IntMap.foldr' @a @b)
+{-# INLINE foldr' #-}
+
+foldl' :: forall x a b. (a -> b -> a) -> a -> IntLikeMap x b -> a
+foldl' = coerce (IntMap.foldl' @a @b)
+{-# INLINE foldl' #-}
+
+foldrWithKey' :: forall x a b. (Coercible x Int) => (x -> a -> b -> b) -> b -> IntLikeMap x a -> b
+foldrWithKey' = coerce (IntMap.foldrWithKey' @a @b)
+{-# INLINE foldrWithKey' #-}
+
+foldlWithKey' :: forall x a b. (Coercible x Int) => (a -> x -> b -> a) -> a -> IntLikeMap x b -> a
+foldlWithKey' = coerce (IntMap.foldlWithKey' @a @b)
+{-# INLINE foldlWithKey' #-}
+
+elems :: forall x a. IntLikeMap x a -> [a]
+elems = coerce (IntMap.elems @a)
+{-# INLINE elems #-}
+
+keys :: forall x a. (Coercible x Int) => IntLikeMap x a -> [x]
+keys = coerce (IntMap.keys @a)
+{-# INLINE keys #-}
+
+assocs :: forall x a. (Coercible x Int) => IntLikeMap x a -> [(x, a)]
+assocs = coerce (IntMap.assocs @a)
+{-# INLINE assocs #-}
+
+keysSet :: forall x a. IntLikeMap x a -> IntLikeSet x
+keysSet = coerce (IntMap.keysSet @a)
+{-# INLINE keysSet #-}
+
+toList :: forall x a. (Coercible x Int) => IntLikeMap x a -> [(x, a)]
+toList = coerce (IntMap.toList @a)
+{-# INLINE toList #-}
+
+toAscList :: forall x a. (Coercible x Int) => IntLikeMap x a -> [(x, a)]
+toAscList = coerce (IntMap.toAscList @a)
+{-# INLINE toAscList #-}
+
+toDescList :: forall x a. (Coercible x Int) => IntLikeMap x a -> [(x, a)]
+toDescList = coerce (IntMap.toDescList @a)
+{-# INLINE toDescList #-}
+
+filter :: forall x a. (a -> Bool) -> IntLikeMap x a -> IntLikeMap x a
+filter = coerce (IntMap.filter @a)
 {-# INLINE filter #-}
 
-restrictKeys :: IntLikeMap x a -> IntLikeSet x -> IntLikeMap x a
-restrictKeys m s = IntLikeMap (IntMap.restrictKeys (unIntLikeMap m) (unIntLikeSet s))
+#if MIN_VERSION_containers(0,8,0)
+filterKeys :: forall x a. (Coercible x Int) => (x -> Bool) -> IntLikeMap x a -> IntLikeMap x a
+filterKeys = coerce (IntMap.filterKeys @a)
+{-# INLINE filterKeys #-}
+#endif
+
+filterWithKey :: forall x a. (Coercible x Int) => (x -> a -> Bool) -> IntLikeMap x a -> IntLikeMap x a
+filterWithKey = coerce (IntMap.filterWithKey @a)
+{-# INLINE filterWithKey #-}
+
+restrictKeys :: forall x a. IntLikeMap x a -> IntLikeSet x -> IntLikeMap x a
+restrictKeys = coerce (IntMap.restrictKeys @a)
 {-# INLINE restrictKeys #-}
 
-map :: (a -> b) -> IntLikeMap x a -> IntLikeMap x b
-map f = IntLikeMap . IntMap.map f . unIntLikeMap
-{-# INLINE map #-}
+withoutKeys :: forall x a. IntLikeMap x a -> IntLikeSet x -> IntLikeMap x a
+withoutKeys = coerce (IntMap.withoutKeys @a)
+{-# INLINE withoutKeys #-}
 
-insertState :: Coercible x Int => (Maybe a -> b) -> x -> a -> IntLikeMap x a -> (b, IntLikeMap x a)
+partition :: forall x a. (a -> Bool) -> IntLikeMap x a -> (IntLikeMap x a, IntLikeMap x a)
+partition = coerce (IntMap.partition @a)
+{-# INLINE partition #-}
+
+partitionWithKey
+  :: forall x a. (Coercible x Int) => (x -> a -> Bool) -> IntLikeMap x a -> (IntLikeMap x a, IntLikeMap x a)
+partitionWithKey = coerce (IntMap.partitionWithKey @a)
+{-# INLINE partitionWithKey #-}
+
+takeWhileAntitone :: forall x a. (Coercible x Int) => (x -> Bool) -> IntLikeMap x a -> IntLikeMap x a
+takeWhileAntitone = coerce (IntMap.takeWhileAntitone @a)
+{-# INLINE takeWhileAntitone #-}
+
+dropWhileAntitone :: forall x a. (Coercible x Int) => (x -> Bool) -> IntLikeMap x a -> IntLikeMap x a
+dropWhileAntitone = coerce (IntMap.dropWhileAntitone @a)
+{-# INLINE dropWhileAntitone #-}
+
+spanAntitone :: forall x a. (Coercible x Int) => (x -> Bool) -> IntLikeMap x a -> (IntLikeMap x a, IntLikeMap x a)
+spanAntitone = coerce (IntMap.spanAntitone @a)
+{-# INLINE spanAntitone #-}
+
+mapMaybe :: forall x a b. (a -> Maybe b) -> IntLikeMap x a -> IntLikeMap x b
+mapMaybe = coerce (IntMap.mapMaybe @a @b)
+{-# INLINE mapMaybe #-}
+
+mapMaybeWithKey :: forall x a b. (Coercible x Int) => (x -> a -> Maybe b) -> IntLikeMap x a -> IntLikeMap x b
+mapMaybeWithKey = coerce (IntMap.mapMaybeWithKey @a @b)
+{-# INLINE mapMaybeWithKey #-}
+
+mapEither
+  :: forall x a b c. (a -> Either b c) -> IntLikeMap x a -> (IntLikeMap x b, IntLikeMap x c)
+mapEither = coerce (IntMap.mapEither @a @b @c)
+{-# INLINE mapEither #-}
+
+mapEitherWithKey
+  :: forall x a b c. (Coercible x Int) => (x -> a -> Either b c) -> IntLikeMap x a -> (IntLikeMap x b, IntLikeMap x c)
+mapEitherWithKey = coerce (IntMap.mapEitherWithKey @a @b @c)
+{-# INLINE mapEitherWithKey #-}
+
+split :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> (IntLikeMap x a, IntLikeMap x a)
+split = coerce (IntMap.split @a)
+{-# INLINE split #-}
+
+splitLookup :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> (IntLikeMap x a, Maybe a, IntLikeMap x a)
+splitLookup = coerce (IntMap.splitLookup @a)
+{-# INLINE splitLookup #-}
+
+splitRoot :: forall x a. IntLikeMap x a -> [IntLikeMap x a]
+splitRoot = coerce (IntMap.splitRoot @a)
+{-# INLINE splitRoot #-}
+
+isSubmapOf :: forall x a. (Eq a) => IntLikeMap x a -> IntLikeMap x a -> Bool
+isSubmapOf = coerce (IntMap.isSubmapOf @a)
+{-# INLINE isSubmapOf #-}
+
+isSubmapOfBy :: forall x a b. (a -> b -> Bool) -> IntLikeMap x a -> IntLikeMap x b -> Bool
+isSubmapOfBy = coerce (IntMap.isSubmapOfBy @a @b)
+{-# INLINE isSubmapOfBy #-}
+
+isProperSubmapOf :: forall x a. (Eq a) => IntLikeMap x a -> IntLikeMap x a -> Bool
+isProperSubmapOf = coerce (IntMap.isProperSubmapOf @a)
+{-# INLINE isProperSubmapOf #-}
+
+isProperSubmapOfBy :: forall x a b. (a -> b -> Bool) -> IntLikeMap x a -> IntLikeMap x b -> Bool
+isProperSubmapOfBy = coerce (IntMap.isProperSubmapOfBy @a @b)
+{-# INLINE isProperSubmapOfBy #-}
+
+lookupMin :: forall x a. (Coercible x Int) => IntLikeMap x a -> Maybe (x, a)
+lookupMin = coerce (IntMap.lookupMin @a)
+{-# INLINE lookupMin #-}
+
+lookupMax :: forall x a. (Coercible x Int) => IntLikeMap x a -> Maybe (x, a)
+lookupMax = coerce (IntMap.lookupMax @a)
+{-# INLINE lookupMax #-}
+
+findMin :: forall x a. (Coercible x Int) => IntLikeMap x a -> (x, a)
+findMin = coerce (IntMap.findMin @a)
+{-# INLINE findMin #-}
+
+findMax :: forall x a. (Coercible x Int) => IntLikeMap x a -> (x, a)
+findMax = coerce (IntMap.findMax @a)
+{-# INLINE findMax #-}
+
+deleteMin :: forall x a. IntLikeMap x a -> IntLikeMap x a
+deleteMin = coerce (IntMap.deleteMin @a)
+{-# INLINE deleteMin #-}
+
+deleteMax :: forall x a. IntLikeMap x a -> IntLikeMap x a
+deleteMax = coerce (IntMap.deleteMax @a)
+{-# INLINE deleteMax #-}
+
+deleteFindMin :: forall x a. (Coercible x Int) => IntLikeMap x a -> ((x, a), IntLikeMap x a)
+deleteFindMin = coerce (IntMap.deleteFindMin @a)
+{-# INLINE deleteFindMin #-}
+
+deleteFindMax :: forall x a. (Coercible x Int) => IntLikeMap x a -> ((x, a), IntLikeMap x a)
+deleteFindMax = coerce (IntMap.deleteFindMax @a)
+{-# INLINE deleteFindMax #-}
+
+updateMin :: forall x a. (a -> Maybe a) -> IntLikeMap x a -> IntLikeMap x a
+updateMin = coerce (IntMap.updateMin @a)
+{-# INLINE updateMin #-}
+
+updateMax :: forall x a. (a -> Maybe a) -> IntLikeMap x a -> IntLikeMap x a
+updateMax = coerce (IntMap.updateMax @a)
+{-# INLINE updateMax #-}
+
+updateMinWithKey :: forall x a. (Coercible x Int) => (x -> a -> Maybe a) -> IntLikeMap x a -> IntLikeMap x a
+updateMinWithKey = coerce (IntMap.updateMinWithKey @a)
+{-# INLINE updateMinWithKey #-}
+
+updateMaxWithKey :: forall x a. (Coercible x Int) => (x -> a -> Maybe a) -> IntLikeMap x a -> IntLikeMap x a
+updateMaxWithKey = coerce (IntMap.updateMaxWithKey @a)
+{-# INLINE updateMaxWithKey #-}
+
+minView :: forall x a. IntLikeMap x a -> Maybe (a, IntLikeMap x a)
+minView = coerce (IntMap.minView @a)
+{-# INLINE minView #-}
+
+maxView :: forall x a. IntLikeMap x a -> Maybe (a, IntLikeMap x a)
+maxView = coerce (IntMap.maxView @a)
+{-# INLINE maxView #-}
+
+minViewWithKey :: forall x a. (Coercible x Int) => IntLikeMap x a -> Maybe ((x, a), IntLikeMap x a)
+minViewWithKey = coerce (IntMap.minViewWithKey @a)
+{-# INLINE minViewWithKey #-}
+
+maxViewWithKey :: forall x a. (Coercible x Int) => IntLikeMap x a -> Maybe ((x, a), IntLikeMap x a)
+maxViewWithKey = coerce (IntMap.maxViewWithKey @a)
+{-# INLINE maxViewWithKey #-}
+
+-- Extras:
+
+partialLookup :: forall x a. (Coercible x Int) => x -> IntLikeMap x a -> a
+partialLookup x m = unIntLikeMap m IntMap.! coerce x
+{-# INLINE partialLookup #-}
+
+insertState :: (Coercible x Int) => (Maybe a -> b) -> x -> a -> IntLikeMap x a -> (b, IntLikeMap x a)
 insertState f x a = coerce . IntMap.alterF (\m -> (f m, Just a)) (coerce x) . unIntLikeMap
 {-# INLINE insertState #-}
-
-mapWithKey :: Coercible x Int => (x -> a -> b) -> IntLikeMap x a -> IntLikeMap x b
-mapWithKey f = IntLikeMap . IntMap.mapWithKey (coerce f) . unIntLikeMap
-{-# INLINE mapWithKey #-}
diff --git a/src/IntLike/MultiMap.hs b/src/IntLike/MultiMap.hs
--- a/src/IntLike/MultiMap.hs
+++ b/src/IntLike/MultiMap.hs
@@ -29,7 +29,7 @@
 size = ILM.size
 {-# INLINE size #-}
 
-toList :: Coercible k Int => IntLikeMultiMap k v -> [(k, IntLikeSet v)]
+toList :: (Coercible k Int) => IntLikeMultiMap k v -> [(k, IntLikeSet v)]
 toList = ILM.toList
 {-# INLINE toList #-}
 
diff --git a/src/IntLike/Set.hs b/src/IntLike/Set.hs
--- a/src/IntLike/Set.hs
+++ b/src/IntLike/Set.hs
@@ -1,24 +1,105 @@
+{-# LANGUAGE CPP #-}
+
 module IntLike.Set
-  ( IntLikeSet (..)
+  ( -- * Set type
+    IntLikeSet (..)
+
+    -- * Construction
   , empty
   , singleton
   , fromList
-  , size
-  , null
-  , member
-  , toList
+#if MIN_VERSION_containers(0,7,0)
+  , fromRange
+#endif
+  , fromAscList
+  , fromDistinctAscList
+
+    -- * Insertion
   , insert
+
+    -- * Deletion
   , delete
+
+    -- * Generalized insertion/deletion
+  , alterF
+
+    -- * Query
+  , member
+  , notMember
+  , lookupLT
+  , lookupGT
+  , lookupLE
+  , lookupGE
+  , null
+  , size
   , isSubsetOf
-  , intersection
-  , difference
+  , isProperSubsetOf
+  , disjoint
+
+    -- * Combine
   , union
   , unions
+  , difference
+  , (\\)
+  , intersection
+#if MIN_VERSION_containers(0,8,0)
+  , intersections
+  , symmetricDifference
+  -- , Intersection (..)
+#endif
+
+    -- * Filter
+  , filter
+  , partition
+  , takeWhileAntitone
+  , dropWhileAntitone
+  , spanAntitone
+  , split
+  , splitMember
+  , splitRoot
+
+    -- * Map
+  , map
+  , mapMonotonic
+
+    -- * Folds
+  , foldr
+  , foldl
+#if MIN_VERSION_containers(0,8,0)
+  , foldMap
+#endif
+
+    -- ** Strict folds
+  , foldr'
+  , foldl'
+
+    -- ** Legacy folds
+  , fold
+
+    -- * Min\/Max
+
+#if MIN_VERSION_containers(0,8,0)
+  , lookupMin
+  , lookupMax
+#endif
   , findMin
+  , findMax
+  , deleteMin
+  , deleteMax
+  , deleteFindMin
+  , deleteFindMax
+  , maxView
   , minView
-  , disjoint
-  , map
-  , filter
+
+    -- * Conversion
+
+    -- ** List
+  , elems
+  , toList
+  , toAscList
+  , toDescList
+
+    -- * Extra
   , insertState
   , orderedPairs
   , unorderedPairs
@@ -27,100 +108,288 @@
 
 import Control.DeepSeq (NFData)
 import Data.Coerce (Coercible, coerce)
-import Data.Foldable (foldl')
 import Data.IntSet (IntSet)
 import qualified Data.IntSet as IntSet
-import Prelude hiding (filter, map, null)
+#if MIN_VERSION_containers(0,8,0)
+import Data.List.NonEmpty (NonEmpty)
+#endif
+import Prelude hiding (filter, foldMap, foldl, foldr, map, null)
 
+type role IntLikeSet nominal
+
 newtype IntLikeSet x = IntLikeSet {unIntLikeSet :: IntSet}
   deriving stock (Show)
   deriving newtype (Eq, Ord, NFData, Semigroup, Monoid)
 
 empty :: IntLikeSet x
-empty = IntLikeSet IntSet.empty
+empty = coerce IntSet.empty
 {-# INLINE empty #-}
 
-singleton :: Coercible x Int => x -> IntLikeSet x
-singleton = IntLikeSet . IntSet.singleton . coerce
+singleton :: (Coercible x Int) => x -> IntLikeSet x
+singleton = coerce IntSet.singleton
 {-# INLINE singleton #-}
 
-fromList :: Coercible x Int => [x] -> IntLikeSet x
-fromList = IntLikeSet . IntSet.fromList . coerce
+fromList :: (Coercible x Int) => [x] -> IntLikeSet x
+fromList = coerce IntSet.fromList
 {-# INLINE fromList #-}
 
-size :: IntLikeSet x -> Int
-size = IntSet.size . unIntLikeSet
-{-# INLINE size #-}
-
-null :: IntLikeSet x -> Bool
-null = IntSet.null . unIntLikeSet
-{-# INLINE null #-}
+#if MIN_VERSION_containers(0,7,0)
+fromRange :: (Coercible x Int) => (x, x) -> IntLikeSet x
+fromRange = coerce IntSet.fromRange
+#endif
 
-member :: Coercible x Int => x -> IntLikeSet x -> Bool
-member x = IntSet.member (coerce x) . unIntLikeSet
-{-# INLINE member #-}
+fromAscList :: (Coercible x Int) => [x] -> IntLikeSet x
+fromAscList = coerce IntSet.fromAscList
 
-toList :: Coercible x Int => IntLikeSet x -> [x]
-toList = coerce . IntSet.toList . unIntLikeSet
-{-# INLINE toList #-}
+fromDistinctAscList :: (Coercible x Int) => [x] -> IntLikeSet x
+fromDistinctAscList = coerce IntSet.fromDistinctAscList
 
-insert :: Coercible x Int => x -> IntLikeSet x -> IntLikeSet x
-insert x = IntLikeSet . IntSet.insert (coerce x) . unIntLikeSet
+insert :: (Coercible x Int) => x -> IntLikeSet x -> IntLikeSet x
+insert = coerce IntSet.insert
 {-# INLINE insert #-}
 
-delete :: Coercible x Int => x -> IntLikeSet x -> IntLikeSet x
-delete x = IntLikeSet . IntSet.delete (coerce x) . unIntLikeSet
+delete :: (Coercible x Int) => x -> IntLikeSet x -> IntLikeSet x
+delete = coerce IntSet.delete
 {-# INLINE delete #-}
 
+alterF
+  :: forall x f
+   . (Coercible x Int)
+  => (forall v u. (Coercible v u) => Coercible (f v) (f u))
+  => (Functor f)
+  => (Bool -> f Bool)
+  -> x
+  -> IntLikeSet x
+  -> f (IntLikeSet x)
+alterF = coerce (IntSet.alterF @f)
+{-# INLINE alterF #-}
+
+member :: (Coercible x Int) => x -> IntLikeSet x -> Bool
+member = coerce IntSet.member
+{-# INLINE member #-}
+
+notMember :: (Coercible x Int) => x -> IntLikeSet x -> Bool
+notMember = coerce IntSet.notMember
+{-# INLINE notMember #-}
+
+lookupLT :: (Coercible x Int) => x -> IntLikeSet x -> Maybe x
+lookupLT = coerce IntSet.lookupLT
+{-# INLINE lookupLT #-}
+
+lookupGT :: (Coercible x Int) => x -> IntLikeSet x -> Maybe x
+lookupGT = coerce IntSet.lookupGT
+{-# INLINE lookupGT #-}
+
+lookupLE :: (Coercible x Int) => x -> IntLikeSet x -> Maybe x
+lookupLE = coerce IntSet.lookupLE
+{-# INLINE lookupLE #-}
+
+lookupGE :: (Coercible x Int) => x -> IntLikeSet x -> Maybe x
+lookupGE = coerce IntSet.lookupGE
+{-# INLINE lookupGE #-}
+
+null :: IntLikeSet x -> Bool
+null = coerce IntSet.null
+{-# INLINE null #-}
+
+size :: IntLikeSet x -> Int
+size = coerce IntSet.size
+{-# INLINE size #-}
+
 isSubsetOf :: IntLikeSet x -> IntLikeSet x -> Bool
-isSubsetOf xs ys = IntSet.isSubsetOf (unIntLikeSet xs) (unIntLikeSet ys)
+isSubsetOf = coerce IntSet.isSubsetOf
 {-# INLINE isSubsetOf #-}
 
-intersection :: IntLikeSet x -> IntLikeSet x -> IntLikeSet x
-intersection xs ys = IntLikeSet (IntSet.intersection (unIntLikeSet xs) (unIntLikeSet ys))
-{-# INLINE intersection #-}
+isProperSubsetOf :: IntLikeSet x -> IntLikeSet x -> Bool
+isProperSubsetOf = coerce IntSet.isProperSubsetOf
+{-# INLINE isProperSubsetOf #-}
 
-difference :: IntLikeSet x -> IntLikeSet x -> IntLikeSet x
-difference xs ys = IntLikeSet (IntSet.difference (unIntLikeSet xs) (unIntLikeSet ys))
-{-# INLINE difference #-}
+disjoint :: IntLikeSet x -> IntLikeSet x -> Bool
+disjoint = coerce IntSet.disjoint
+{-# INLINE disjoint #-}
 
 union :: IntLikeSet x -> IntLikeSet x -> IntLikeSet x
-union xs ys = IntLikeSet (IntSet.union (unIntLikeSet xs) (unIntLikeSet ys))
+union = coerce IntSet.union
 {-# INLINE union #-}
 
--- Copied here because coercion through f is difficult
-unions :: Foldable f => f (IntLikeSet x) -> IntLikeSet x
-unions = foldl' union empty
+unions
+  :: forall x f
+   . (forall v u. (Coercible v u) => Coercible (f v) (f u))
+  => (Foldable f)
+  => f (IntLikeSet x)
+  -> IntLikeSet x
+unions = coerce (IntSet.unions @f)
 {-# INLINE unions #-}
 
-findMin :: Coercible x Int => IntLikeSet x -> x
-findMin = coerce . IntSet.findMin . unIntLikeSet
-{-# INLINE findMin #-}
+difference :: IntLikeSet x -> IntLikeSet x -> IntLikeSet x
+difference = coerce IntSet.difference
+{-# INLINE difference #-}
 
-minView :: Coercible x Int => IntLikeSet x -> Maybe (x, IntLikeSet x)
-minView = coerce . IntSet.minView . unIntLikeSet
-{-# INLINE minView #-}
+(\\) :: IntLikeSet x -> IntLikeSet x -> IntLikeSet x
+(\\) = coerce (IntSet.\\)
+{-# INLINE (\\) #-}
 
-disjoint :: IntLikeSet x -> IntLikeSet x -> Bool
-disjoint a b = IntSet.disjoint (unIntLikeSet a) (unIntLikeSet b)
-{-# INLINE disjoint #-}
+intersection :: IntLikeSet x -> IntLikeSet x -> IntLikeSet x
+intersection = coerce IntSet.intersection
+{-# INLINE intersection #-}
 
-map :: (Coercible x Int, Coercible y Int) => (x -> y) -> IntLikeSet x -> IntLikeSet y
-map f = IntLikeSet . IntSet.map (coerce f) . unIntLikeSet
-{-# INLINE map #-}
+#if MIN_VERSION_containers(0,8,0)
 
+intersections :: NonEmpty (IntLikeSet x) -> IntLikeSet x
+intersections = coerce IntSet.intersections
+{-# INLINE intersections #-}
+
+symmetricDifference :: IntLikeSet x -> IntLikeSet x -> IntLikeSet x
+symmetricDifference = coerce IntSet.symmetricDifference
+{-# INLINE symmetricDifference #-}
+
+newtype Intersection = Intersection {getIntersection :: IntSet}
+   deriving stock (Show, Eq, Ord)
+   deriving newtype Semigroup
+
+#endif
+
 filter :: (Coercible x Int) => (x -> Bool) -> IntLikeSet x -> IntLikeSet x
-filter f = IntLikeSet . IntSet.filter (coerce f) . unIntLikeSet
+filter = coerce IntSet.filter
 {-# INLINE filter #-}
 
-insertState :: Coercible x Int => (Bool -> b) -> x -> IntLikeSet x -> (b, IntLikeSet x)
+partition :: (Coercible x Int) => (x -> Bool) -> IntLikeSet x -> (IntLikeSet x, IntLikeSet x)
+partition = coerce IntSet.partition
+{-# INLINE partition #-}
+
+takeWhileAntitone :: (Coercible x Int) => (x -> Bool) -> IntLikeSet x -> IntLikeSet x
+takeWhileAntitone = coerce IntSet.takeWhileAntitone
+{-# INLINE takeWhileAntitone #-}
+
+dropWhileAntitone :: (Coercible x Int) => (x -> Bool) -> IntLikeSet x -> IntLikeSet x
+dropWhileAntitone = coerce IntSet.dropWhileAntitone
+{-# INLINE dropWhileAntitone #-}
+
+spanAntitone :: (Coercible x Int) => (x -> Bool) -> IntLikeSet x -> (IntLikeSet x, IntLikeSet x)
+spanAntitone = coerce IntSet.spanAntitone
+{-# INLINE spanAntitone #-}
+
+split :: (Coercible x Int) => x -> IntLikeSet x -> (IntLikeSet x, IntLikeSet x)
+split = coerce IntSet.split
+{-# INLINE split #-}
+
+splitMember :: (Coercible x Int) => x -> IntLikeSet x -> (IntLikeSet x, Bool, IntLikeSet x)
+splitMember = coerce IntSet.splitMember
+{-# INLINE splitMember #-}
+
+splitRoot :: IntLikeSet x -> [IntLikeSet x]
+splitRoot = coerce IntSet.splitRoot
+{-# INLINE splitRoot #-}
+
+map :: (Coercible x Int, Coercible y Int) => (x -> y) -> IntLikeSet x -> IntLikeSet y
+map = coerce IntSet.map
+{-# INLINE map #-}
+
+mapMonotonic :: (Coercible x Int) => (x -> x) -> IntLikeSet x -> IntLikeSet x
+mapMonotonic = coerce IntSet.mapMonotonic
+{-# INLINE mapMonotonic #-}
+
+foldr :: forall x b. (Coercible x Int) => (x -> b -> b) -> b -> IntLikeSet x -> b
+foldr = coerce (IntSet.foldr @b)
+{-# INLINE foldr #-}
+
+foldl :: forall x a. (Coercible x Int) => (a -> x -> a) -> a -> IntLikeSet x -> a
+foldl = coerce (IntSet.foldl @a)
+{-# INLINE foldl #-}
+
+#if MIN_VERSION_containers(0,8,0)
+foldMap :: forall x a. (Coercible x Int) => (Monoid a) => (x -> a) -> IntLikeSet x -> a
+foldMap = coerce (IntSet.foldMap @a)
+{-# INLINE foldMap #-}
+#endif
+
+foldr' :: forall x b. (Coercible x Int) => (x -> b -> b) -> b -> IntLikeSet x -> b
+foldr' = coerce (IntSet.foldr' @b)
+{-# INLINE foldr' #-}
+
+foldl' :: forall x a. (Coercible x Int) => (a -> x -> a) -> a -> IntLikeSet x -> a
+foldl' = coerce (IntSet.foldl' @a)
+{-# INLINE foldl' #-}
+
+#if MIN_VERSION_containers(0,8,0)
+-- Mirror the deprecation message from containers 0.8
+{-# DEPRECATED fold "Use IntLike.Set.foldr instead" #-}
+#endif
+
+fold :: forall x b. (Coercible x Int) => (x -> b -> b) -> b -> IntLikeSet x -> b
+fold = coerce (IntSet.fold @b)
+{-# INLINE fold #-}
+
+#if MIN_VERSION_containers(0,8,0)
+
+lookupMin :: (Coercible x Int) => IntLikeSet x -> Maybe x
+lookupMin = coerce (IntSet.lookupMin)
+{-# INLINE lookupMin #-}
+
+lookupMax :: (Coercible x Int) => IntLikeSet x -> Maybe x
+lookupMax = coerce (IntSet.lookupMax)
+{-# INLINE lookupMax #-}
+
+#endif
+
+findMin :: (Coercible x Int) => IntLikeSet x -> x
+findMin = coerce IntSet.findMin
+{-# INLINE findMin #-}
+
+findMax :: (Coercible x Int) => IntLikeSet x -> x
+findMax = coerce IntSet.findMax
+{-# INLINE findMax #-}
+
+deleteMin :: IntLikeSet x -> IntLikeSet x
+deleteMin = coerce IntSet.deleteMin
+{-# INLINE deleteMin #-}
+
+deleteMax :: IntLikeSet x -> IntLikeSet x
+deleteMax = coerce IntSet.deleteMax
+{-# INLINE deleteMax #-}
+
+deleteFindMin :: (Coercible x Int) => IntLikeSet x -> (x, IntLikeSet x)
+deleteFindMin = coerce IntSet.deleteFindMin
+{-# INLINE deleteFindMin #-}
+
+deleteFindMax :: (Coercible x Int) => IntLikeSet x -> (x, IntLikeSet x)
+deleteFindMax = coerce IntSet.deleteFindMax
+{-# INLINE deleteFindMax #-}
+
+maxView :: (Coercible x Int) => IntLikeSet x -> Maybe (x, IntLikeSet x)
+maxView = coerce IntSet.maxView
+{-# INLINE maxView #-}
+
+minView :: (Coercible x Int) => IntLikeSet x -> Maybe (x, IntLikeSet x)
+minView = coerce IntSet.minView
+{-# INLINE minView #-}
+
+elems :: (Coercible x Int) => IntLikeSet x -> [x]
+elems = coerce IntSet.elems
+{-# INLINE elems #-}
+
+toList :: (Coercible x Int) => IntLikeSet x -> [x]
+toList = coerce IntSet.toList
+{-# INLINE toList #-}
+
+toAscList :: (Coercible x Int) => IntLikeSet x -> [x]
+toAscList = coerce IntSet.toAscList
+{-# INLINE toAscList #-}
+
+toDescList :: (Coercible x Int) => IntLikeSet x -> [x]
+toDescList = coerce IntSet.toDescList
+{-# INLINE toDescList #-}
+
+-- Extras:
+
+insertState :: (Coercible x Int) => (Bool -> b) -> x -> IntLikeSet x -> (b, IntLikeSet x)
 insertState f x = coerce . IntSet.alterF (\b -> (f b, True)) (coerce x) . unIntLikeSet
 {-# INLINE insertState #-}
 
-orderedPairs :: Coercible x Int => IntLikeSet x -> [(x, x)]
+orderedPairs :: (Coercible x Int) => IntLikeSet x -> [(x, x)]
 orderedPairs s = let vs = toList s in [(x, y) | x <- vs, y <- vs]
 
-unorderedPairs :: Coercible x Int => IntLikeSet x -> [(x, x)]
+unorderedPairs :: (Coercible x Int) => IntLikeSet x -> [(x, x)]
 unorderedPairs = go1 . toList
  where
   go1 vs =
