diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# New in 0.1.4.0
+
+- `srandmembersN` command added
+
 # New in 0.1.3.0
 
 - `mset` command with batch processing.
diff --git a/hlrdb-core.cabal b/hlrdb-core.cabal
--- a/hlrdb-core.cabal
+++ b/hlrdb-core.cabal
@@ -1,5 +1,5 @@
 name:                hlrdb-core
-version:             0.1.4.0
+version:             0.1.5.0
 synopsis:            High-level Redis Database Core API
 description:         A library for type-driven interaction with Redis
 license:             MIT
@@ -29,14 +29,14 @@
     , HLRDB.Structures.SSet
     , HLRDB.Internal
   build-depends: base >= 4.9 && < 5.0
-               , bytestring ^>= 0.10.8.2
-               , hashable (>= 1.2.6.1 && < 1.2.7.0) || ^>= 1.2.7.0
-               , hedis (>= 0.10.1 && <= 0.12.4) || ^>= 0.12.4
-               , lens (>= 4.16 && <= 4.17.1) || ^>= 4.17.1
+               , bytestring (>= 0.10.8.2 && < 0.10.10.0) || ^>= 0.10.10.0
+               , hashable (>= 1.2.6.1 && < 1.3) || ^>= 1.3
+               , hedis (>= 0.10.1 && <= 0.12.10) || ^>= 0.12.10
+               , lens (>= 4.16 && <= 4.18.1) || ^>= 4.18.1
                , mtl ^>= 2.2.2
-               , profunctors (>= 5.2.2 && <= 5.3) || ^>= 5.3
+               , profunctors (>= 5.2.2 && <= 5.5.1) || ^>= 5.5.1
                , random ^>= 1.1
-               , time (>=1.6 && <1.9.1) || ^>= 1.9.2
+               , time (>=1.6 && <1.9.3) || ^>= 1.9.3
                , unordered-containers (>= 0.2.8.0 && < 0.2.10.0) || ^>= 0.2.10.0
   hs-source-dirs:      src
   default-language:    Haskell2010
diff --git a/src/HLRDB/Core.hs b/src/HLRDB/Core.hs
--- a/src/HLRDB/Core.hs
+++ b/src/HLRDB/Core.hs
@@ -5,8 +5,7 @@
 -- When using this package, you should always ensure that your Eq instances respect the induced equality via whatever serialization mechanism you've specified, since many commands perform comparisons in Redis directly.
 
 module HLRDB.Core
-       (
-         -- * Basic
+       ( -- * Basic
          get
        , liftq
        , mget
diff --git a/src/HLRDB/Internal.hs b/src/HLRDB/Internal.hs
--- a/src/HLRDB/Internal.hs
+++ b/src/HLRDB/Internal.hs
@@ -1,8 +1,7 @@
 -- | Internal module. Not intended for public use.
 
 module HLRDB.Internal
-       (
-         probIO
+       ( probIO
        , primKey
        , unwrap
        , unwrapCursor
@@ -32,7 +31,7 @@
 import System.Random (randomRIO)
 
 
-probIO :: (MonadIO m) => Double -> m a -> m (Maybe a)
+probIO :: MonadIO m => Double -> m a -> m (Maybe a)
 probIO pr a =
   if pr >= 1.0 then Just <$> a else do
     r :: Double <- liftIO $ randomRIO (0, 1.0)
@@ -100,9 +99,10 @@
   xs -> liftRedis $ f xs
 
 {-# INLINE foldM #-}
-foldM :: (Foldable t) => (a -> b) -> t a -> [ b ]
+foldM :: Foldable t => (a -> b) -> t a -> [ b ]
 foldM f t = foldr (\a xs -> f a : xs) [] t
 
+{-# INLINE decodeMInteger #-}
 decodeMInteger :: Maybe ByteString -> Int64
 decodeMInteger Nothing = 0
 decodeMInteger (Just bs) = readInt bs
@@ -140,9 +140,11 @@
 newtype MSET = MSET { runMSET :: DList (ByteString , Maybe ByteString) }
 
 instance Semigroup MSET where
+  {-# INLINE (<>) #-}
   (<>) (MSET as) (MSET bs) = MSET (as . bs)
 
 instance Monoid MSET where
+  {-# INLINE mempty #-}
   mempty = MSET $ (<>) []
 
 splitWith :: (a -> Either b c) -> [ a ] -> ([ b ] , [ c ])
diff --git a/src/HLRDB/Primitives/Aggregate.hs b/src/HLRDB/Primitives/Aggregate.hs
--- a/src/HLRDB/Primitives/Aggregate.hs
+++ b/src/HLRDB/Primitives/Aggregate.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE BlockArguments #-}
+
 -- | Combinators that can be used for aggregating independent queries. See my <https://identicalsnowflake.github.io/QueryAggregation.html article> about aggregating mget queries for more information.
 
 module HLRDB.Primitives.Aggregate
@@ -8,12 +10,14 @@
        , type Query
        , aggregatePair
        , remember
+       , bitraverse'
        , runT
 
        -- | Aggregate, atomic multi-set query (as in setting multiple things in a single query)
        , MSET
        ) where
 
+import Data.Bitraversable
 import Data.Profunctor
 import Data.Profunctor.Traversing
 import Control.Lens hiding (Traversing)
@@ -25,14 +29,22 @@
 newtype T x y a b = T (Traversal a b x y) deriving (Functor)
 
 instance Profunctor (T x y) where
-  dimap f g (T t) = T $ \m -> fmap g . t m . f
+  {-# INLINE lmap #-}
+  lmap f (T t) = T \x -> t x . f
+  {-# INLINE rmap #-}
+  rmap g (T t) = T \x -> fmap g . t x
+  {-# INLINE dimap #-}
+  dimap f g (T t) = T \m -> fmap g . t m . f
 
 instance Traversing (T x y) where
+  {-# INLINE traverse' #-}
   traverse' (T t) = T (traverse . t)
 
 instance Applicative (T x y a) where
+  {-# INLINE pure #-}
   pure x = T $ \_ _ -> pure x
-  (<*>) (T f) (T x) = T $ \g a -> f g a <*> x g a
+  {-# INLINE (<*>) #-}
+  (<*>) (T f) (T x) = T \g a -> f g a <*> x g a
 
 -- | We can merge any two arbitrary mget queries.
 {-# INLINE aggregatePair #-}
@@ -42,14 +54,24 @@
 
 -- Remember could probably be a Profunctor typeclass in general (is it?)
 -- | And we can remember the lookup
+{-# INLINE remember #-}
 remember :: T x y a b -> T x y a (a , b)
-remember (T f) = T $ \x a -> (,) a <$> f x a
+remember (T f) = T \x a -> (,) a <$> f x a
 
+{-# INLINABLE bitraverse' #-}
+bitraverse' :: Bitraversable t => a ~~> b -> c ~~> d -> t a c ~~> t b d
+bitraverse' x y = rev' (bitraverse (flip lmap x . const) (flip lmap y . const))
+      where
+        rev' :: (a -> () ~~> b) -> a ~~> b
+        rev' f = T \g v -> case f v of
+          T m -> m g ()
 
 instance Strong (T x y) where
+  {-# INLINE first' #-}
   first' = firstTraversing
 
 instance Choice (T x y) where
+  {-# INLINE left' #-}
   left' = leftTraversing
 
 -- | Reify aggregation into a target functor.
