diff --git a/Data/Conduit/Binary.hs b/Data/Conduit/Binary.hs
--- a/Data/Conduit/Binary.hs
+++ b/Data/Conduit/Binary.hs
@@ -30,13 +30,14 @@
     , drop
     , sinkCacheLength
     , sinkLbs
+    , mapM_
       -- ** Conduits
     , isolate
     , takeWhile
     , Data.Conduit.Binary.lines
     ) where
 
-import Prelude hiding (head, take, drop, takeWhile, dropWhile)
+import Prelude hiding (head, take, drop, takeWhile, dropWhile, mapM_)
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Lazy as L
 import Data.Conduit
@@ -45,6 +46,7 @@
 import Control.Monad (unless)
 import Control.Monad.IO.Class (liftIO, MonadIO)
 import Control.Monad.Trans.Resource (allocate, release)
+import Control.Monad.Trans.Class (lift)
 import qualified System.IO as IO
 import Data.Word (Word8, Word64)
 import Control.Applicative ((<$>))
@@ -377,3 +379,20 @@
 -- Since 1.0.5
 sinkLbs :: Monad m => Sink S.ByteString m L.ByteString
 sinkLbs = fmap L.fromChunks consume
+
+-- | Perform a computation on each @Word8@ in a stream.
+--
+-- Since 1.0.10
+mapM_ :: Monad m => (Word8 -> m ()) -> Consumer S.ByteString m ()
+mapM_ f =
+    awaitForever (lift . go)
+  where
+    go bs =
+        loop 0
+      where
+        len = S.length bs
+        loop i
+            | i < len = do
+                f (S.index bs i)
+                loop (i + 1)
+            | otherwise = return ()
diff --git a/Data/Conduit/Util.hs b/Data/Conduit/Util.hs
--- a/Data/Conduit/Util.hs
+++ b/Data/Conduit/Util.hs
@@ -3,12 +3,14 @@
     ( -- * Misc
       zip
     , zipSinks
+    , passthroughSink
     ) where
 
 import Prelude hiding (zip)
 import Control.Monad (liftM, liftM2)
-import Data.Conduit.Internal (Pipe (..), Source, Sink, injectLeftovers, ConduitM (..))
+import Data.Conduit.Internal (Pipe (..), Source, Sink, injectLeftovers, ConduitM (..), Conduit, awaitForever, yield, await)
 import Data.Void (Void, absurd)
+import Control.Monad.Trans.Class (lift)
 
 -- | Combines two sources. The new source will stop producing once either
 --   source has been exhausted.
@@ -55,3 +57,40 @@
     NeedInput px cx  >< NeedInput py cy  = NeedInput (\i -> px i >< py i) (\() -> cx () >< cy ())
     NeedInput px cx  >< y@Done{}         = NeedInput (\i -> px i >< y)    (\u -> cx u >< y)
     x@Done{}         >< NeedInput py cy  = NeedInput (\i -> x >< py i)    (\u -> x >< cy u)
+
+-- | Turn a @Sink@ into a @Conduit@ in the following way:
+--
+-- * All input passed to the @Sink@ is yielded downstream.
+--
+-- * When the @Sink@ finishes processing, the result is passed to the provided to the finalizer function.
+--
+-- Note that the @Sink@ will stop receiving input as soon as the downstream it
+-- is connected to shuts down.
+--
+-- An example usage would be to write the result of a @Sink@ to some mutable
+-- variable while allowing other processing to continue.
+--
+-- Since 1.0.10
+passthroughSink :: Monad m
+                => Sink i m r
+                -> (r -> m ()) -- ^ finalizer
+                -> Conduit i m i
+passthroughSink (ConduitM sink0) final =
+    ConduitM $ go [] sink0
+  where
+    go _ (Done r) = do
+        lift $ final r
+        awaitForever yield
+    go is (Leftover sink i) = go (i:is) sink
+    go _ (HaveOutput _ _ o) = absurd o
+    go is (PipeM mx) = do
+        x <- lift mx
+        go is x
+    go (i:is) (NeedInput next _) = go is (next i)
+    go [] (NeedInput next done) = do
+        mx <- await
+        case mx of
+            Nothing -> go [] (done ())
+            Just x -> do
+                yield x
+                go [] (next x)
diff --git a/conduit.cabal b/conduit.cabal
--- a/conduit.cabal
+++ b/conduit.cabal
@@ -1,5 +1,5 @@
 Name:                conduit
-Version:             1.0.9.3
+Version:             1.0.10
 Synopsis:            Streaming data processing library.
 Description:
     @conduit@ is a solution to the streaming data problem, allowing for production, transformation, and consumption of streams of data in constant memory. It is an alternative to lazy I\/O which guarantees deterministic resource handling, and fits in the same general solution space as @enumerator@\/@iteratee@ and @pipes@. For a tutorial, please visit <https://haskell.fpcomplete.com/user/snoyberg/library-documentation/conduit-overview>.
diff --git a/test/main.hs b/test/main.hs
--- a/test/main.hs
+++ b/test/main.hs
@@ -936,6 +936,33 @@
                 lbs' `shouldBe` lbs
                 fromIntegral len `shouldBe` L.length lbs'
 
+    describe "Data.Conduit.Binary.mapM_" $ do
+        prop "telling works" $ \bytes ->
+            let lbs = L.pack bytes
+                src = CB.sourceLbs lbs
+                sink = CB.mapM_ (tell . return . S.singleton)
+                bss = execWriter $ src C.$$ sink
+             in L.fromChunks bss == lbs
+
+    describe "passthroughSink" $ do
+        it "works" $ do
+            ref <- I.newIORef (-1)
+            let sink = CL.fold (+) (0 :: Int)
+                conduit = C.passthroughSink sink (I.writeIORef ref)
+                input = [1..10]
+            output <- mapM_ C.yield input C.$$ conduit C.=$ CL.consume
+            output `shouldBe` input
+            x <- I.readIORef ref
+            x `shouldBe` sum input
+        it "does nothing when downstream does nothing" $ do
+            ref <- I.newIORef (-1)
+            let sink = CL.fold (+) (0 :: Int)
+                conduit = C.passthroughSink sink (I.writeIORef ref)
+                input = [undefined]
+            mapM_ C.yield input C.$$ conduit C.=$ return ()
+            x <- I.readIORef ref
+            x `shouldBe` (-1)
+
     describe "mtl instances" $ do
         it "ErrorT" $ do
             let src = flip catchError (const $ C.yield 4) $ do
