diff --git a/library/Potoki/Core/Fetch.hs b/library/Potoki/Core/Fetch.hs
--- a/library/Potoki/Core/Fetch.hs
+++ b/library/Potoki/Core/Fetch.hs
@@ -23,6 +23,7 @@
   vector,
   handlingElements,
   lazyByteStringRef,
+  enumUntil,
 )
 where
 
@@ -293,3 +294,14 @@
         writeIORef ref remainders
         return (Just chunk)
       B.Empty -> return Nothing
+
+{-# INLINE enumUntil #-}
+enumUntil :: (Enum a, Ord a) => IORef a -> a -> Fetch a
+enumUntil ref maxIndex =
+  Fetch $ do
+    index <- readIORef ref
+    if index <= maxIndex
+      then do
+        writeIORef ref (succ index)
+        return (Just index)
+      else return Nothing
diff --git a/library/Potoki/Core/Produce.hs b/library/Potoki/Core/Produce.hs
--- a/library/Potoki/Core/Produce.hs
+++ b/library/Potoki/Core/Produce.hs
@@ -13,6 +13,7 @@
   finiteMVar,
   infiniteMVar,
   lazyByteString,
+  enumInRange,
 )
 where
 
@@ -217,3 +218,10 @@
   Produce $ M.Acquire $ do
     ref <- newIORef lbs
     return (A.lazyByteStringRef ref, return ())
+
+{-# INLINE enumInRange #-}
+enumInRange :: (Enum a, Ord a) => a -> a -> Produce a
+enumInRange from to =
+  Produce $ M.Acquire $ do
+    ref <- newIORef from
+    return (A.indicesUntil ref to, return ())
diff --git a/potoki-core.cabal b/potoki-core.cabal
--- a/potoki-core.cabal
+++ b/potoki-core.cabal
@@ -1,7 +1,7 @@
 name:
   potoki-core
 version:
-  2.2.1.1
+  2.2.2
 synopsis:
   Low-level components of "potoki"
 description:
@@ -61,15 +61,15 @@
     Potoki.Core.IO.Fetch
   build-depends:
     acquire >=0.2 && <0.3,
-    base >=4.7 && <5,
-    profunctors >=5.2 && <6,
-    stm >=2.4 && <3,
     attoparsec >=0.13 && <0.15,
+    base >=4.7 && <5,
     bytestring ==0.10.*,
     directory >=1.3 && <2,
     foldl >=1.3 && <2,
     hashable >=1 && <2,
+    profunctors >=5.2 && <6,
     ptr >=0.16.2 && <0.17,
+    stm >=2.4 && <3,
     text >=1 && <2,
     transformers >=0.5 && <0.6,
     unagi-chan >=0.4 && <0.5,
