diff --git a/Data/Conduit/Internal.hs b/Data/Conduit/Internal.hs
--- a/Data/Conduit/Internal.hs
+++ b/Data/Conduit/Internal.hs
@@ -440,7 +440,20 @@
 transPipe f (HaveOutput p c o) = HaveOutput (transPipe f p) (f c) o
 transPipe f (NeedInput p c) = NeedInput (transPipe f . p) (transPipe f . c)
 transPipe _ (Done r) = Done r
-transPipe f (PipeM mp) = PipeM (f $ liftM (transPipe f) mp)
+transPipe f (PipeM mp) =
+    PipeM (f $ liftM (transPipe f) $ collapse mp)
+  where
+    -- Combine a series of monadic actions into a single action.  Since we
+    -- throw away side effects between different actions, an arbitrary break
+    -- between actions will lead to a violation of the monad transformer laws.
+    -- Example available at:
+    --
+    -- http://hpaste.org/75520
+    collapse mpipe = do
+        pipe <- mpipe
+        case pipe of
+            PipeM mpipe' -> collapse mpipe'
+            _ -> return pipe
 transPipe f (Leftover p i) = Leftover (transPipe f p) i
 
 -- | Apply a function to all the output values of a @Pipe@.
diff --git a/conduit.cabal b/conduit.cabal
--- a/conduit.cabal
+++ b/conduit.cabal
@@ -1,5 +1,5 @@
 Name:                conduit
-Version:             0.5.2.4
+Version:             0.5.2.5
 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 brief tutorial, please see the "Data.Conduit" module.
diff --git a/test/main.hs b/test/main.hs
--- a/test/main.hs
+++ b/test/main.hs
@@ -27,7 +27,8 @@
 import Control.Concurrent (threadDelay, killThread)
 import Control.Monad.IO.Class (liftIO)
 import Control.Monad.Trans.Class (lift)
-import Control.Monad.Trans.Writer (execWriter, tell)
+import Control.Monad.Trans.Writer (execWriter, tell, runWriterT)
+import Control.Monad.Trans.State (evalStateT, get, put)
 import Control.Applicative (pure, (<$>), (<*>))
 import Data.Functor.Identity (runIdentity)
 import Control.Monad (forever)
@@ -794,6 +795,25 @@
         it "conduit" $ do
             let run p = execWriter $ src C.$$ p C.=$ printer
             run ((p3 C.=$= p2) C.=$= p1) `shouldBe` run (p3 C.=$= (p2 C.=$= p1))
+    describe "monad transformer laws" $ do
+        it "transPipe" $ do
+            let source = CL.sourceList $ replicate 10 ()
+            let tell' x = tell [x :: Int]
+
+            let replaceNum1 = C.awaitForever $ \() -> do
+                    i <- lift get
+                    lift $ (put $ i + 1) >> (get >>= lift . tell')
+                    C.yield i
+
+            let replaceNum2 = C.awaitForever $ \() -> do
+                    i <- lift get
+                    lift $ put $ i + 1
+                    lift $ get >>= lift . tell'
+                    C.yield i
+
+            x <- runWriterT $ source C.$$ C.transPipe (`evalStateT` 1) replaceNum1 C.=$ CL.consume
+            y <- runWriterT $ source C.$$ C.transPipe (`evalStateT` 1) replaceNum2 C.=$ CL.consume
+            x `shouldBe` y
 
 it' :: String -> IO () -> Spec
 it' = it
