diff --git a/library/Potoki/Core/Transform.hs b/library/Potoki/Core/Transform.hs
--- a/library/Potoki/Core/Transform.hs
+++ b/library/Potoki/Core/Transform.hs
@@ -40,6 +40,9 @@
   appendBytesToFile,
   writeTextToFile,
   -- * Debugging
+  count,
+  mapInIOWithCounter,
+  handleCount,
   traceWithCounter,
 )
 where
diff --git a/library/Potoki/Core/Transform/Basic.hs b/library/Potoki/Core/Transform/Basic.hs
--- a/library/Potoki/Core/Transform/Basic.hs
+++ b/library/Potoki/Core/Transform/Basic.hs
@@ -125,17 +125,33 @@
     Transform acquire <- liftIO io
     acquire fetch
 
+count :: Transform a Int
+count = Transform $ \ (Fetch fetchIO) -> do
+  counter <- liftIO (newIORef 0)
+  return $ Fetch $ do
+    result <- fetchIO
+    case result of
+      Just _ -> Just <$> atomicModifyIORef' counter (\ n -> (succ n, n))
+      Nothing -> return Nothing
+
+mapInIOWithCounter :: (Int -> a -> IO b) -> Transform a b
+mapInIOWithCounter handler =
+  ioTransform $ do
+    counter <- newIORef 0
+    return $ mapInIO $ \ a -> do
+      count <- atomicModifyIORef' counter (\ n -> (succ n, n))
+      handler count a
+
+handleCount :: (Int -> IO ()) -> Transform a a
+handleCount handler = mapInIOWithCounter $ \ count a -> do
+  handler count
+  return a
+
 {-|
 Useful for debugging
 -}
 traceWithCounter :: (Int -> String) -> Transform a a
-traceWithCounter showFunc =
-  ioTransform $ do
-    counter <- newIORef 0
-    return $ mapInIO $ \ x -> do
-      n <- atomicModifyIORef' counter (\ n -> (succ n, n))
-      putStrLn (showFunc n)
-      return x
+traceWithCounter shower = handleCount (putStrLn . shower)
 
 {-# INLINE consume #-}
 consume :: Consume input output -> Transform input output
diff --git a/potoki-core.cabal b/potoki-core.cabal
--- a/potoki-core.cabal
+++ b/potoki-core.cabal
@@ -1,5 +1,5 @@
 name: potoki-core
-version: 2.2.7
+version: 2.2.8
 synopsis: Low-level components of "potoki"
 description:
   Provides everything required for building custom instances of
