diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.2.3 (2022-08-18)
+
+#### Added
+
+- Add `for :: Monad m => ByteStream m r -> (P.ByteString -> ByteStream m r) -> ByteStream m r`
+
 ## 0.2.2 (2022-05-18)
 
 #### Changed
diff --git a/lib/Streaming/ByteString.hs b/lib/Streaming/ByteString.hs
--- a/lib/Streaming/ByteString.hs
+++ b/lib/Streaming/ByteString.hs
@@ -72,6 +72,7 @@
 
     -- * Transforming ByteStreams
   , map
+  , for
   , intercalate
   , intersperse
 
@@ -638,6 +639,17 @@
 map :: Monad m => (Word8 -> Word8) -> ByteStream m r -> ByteStream m r
 map f z = dematerialize z Empty (Chunk . B.map f) Go
 {-# INLINE map #-}
+
+-- | @'for' xs f@ applies @f@ to each chunk in the stream, and
+-- concatenates the resulting streams.
+--
+-- @since 0.2.3
+for :: Monad m => ByteStream m r -> (P.ByteString -> ByteStream m r) -> ByteStream m r
+for stream f = case stream of
+  Empty r -> Empty r
+  Chunk bs bss -> f bs *> for bss f
+  Go m -> Go ((`for` f) <$> m)
+{-# INLINE for #-}
 
 -- -- | /O(n)/ 'reverse' @xs@ returns the elements of @xs@ in reverse order.
 -- reverse :: ByteString -> ByteString
diff --git a/streaming-bytestring.cabal b/streaming-bytestring.cabal
--- a/streaming-bytestring.cabal
+++ b/streaming-bytestring.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               streaming-bytestring
-version:            0.2.2
+version:            0.2.3
 synopsis:           Fast, effectful byte streams.
 description:
   This library enables fast and safe streaming of byte data, in either @Word8@ or
diff --git a/tests/Test.hs b/tests/Test.hs
--- a/tests/Test.hs
+++ b/tests/Test.hs
@@ -370,6 +370,11 @@
         unpackToString (Q8.concat (Q8.lineSplit n (fromString str))) == str
     , testProperty "concat after lineSplit round trips (CRLF)" $ over ((,) <$> nats <~> strSeriesCrlf) $ \(n,str) ->
         unpackToString (Q8.concat (Q8.lineSplit n (fromString str))) == str
+    , testProperty "'for' is equivalent to the one in streaming" $ over chunksSeries $ \ss ->
+        let doubleStream b = S.each [b, b]
+            doubleByteStream b = Q.chunk b *> Q.chunk b
+        in unpackToString (Q.fromChunks (S.for (Q.toChunks (fromChunks ss)) doubleStream))
+           == unpackToString (Q.for (fromChunks ss) doubleByteStream)
     ]
   , testGroup "Unit Tests"
     [ testCase "hGetContents: Handle stays open" handleIsOpen
