diff --git a/pipes-misc.cabal b/pipes-misc.cabal
--- a/pipes-misc.cabal
+++ b/pipes-misc.cabal
@@ -1,5 +1,5 @@
 name:                pipes-misc
-version:             0.2.4.0
+version:             0.2.5.0
 synopsis:            Miscellaneous utilities for pipes, required by glazier-tutorial
 description:         Please see README.md
 homepage:            https://github.com/louispan/pipes-misc#readme
@@ -25,6 +25,7 @@
                      , clock >= 0.7 && < 1
                      , lens >= 4 && < 5
                      , Decimal >= 0.4 && < 1
+                     , mmorph >= 1 && < 2
                      , mtl >= 2 && < 3
                      , pipes >= 4 && < 5
                      , pipes-category >= 0.2 && < 0.3
diff --git a/src/Pipes/Misc/State/Lazy.hs b/src/Pipes/Misc/State/Lazy.hs
--- a/src/Pipes/Misc/State/Lazy.hs
+++ b/src/Pipes/Misc/State/Lazy.hs
@@ -2,9 +2,14 @@
 
 module Pipes.Misc.State.Lazy where
 
+import Control.Concurrent.STM
 import Control.Lens
+import Control.Monad.Morph
+import Control.Monad.Reader
 import Control.Monad.State.Lazy
 import qualified Pipes as P
+import qualified Pipes.Concurrent as PC
+import qualified Pipes.Misc.Concurrent as PM
 import qualified Pipes.Prelude as PP
 
 -- | Store the output of the pipe into a MonadState.
@@ -38,3 +43,21 @@
     f s
     pure a
 {-# INLINABLE onState #-}
+
+-- | Converts a 'Glazier.Gadget' into a 'Pipes.Pipe'
+rsPipe :: (Monad m, MonadTrans t, MonadState s (t m)) => ReaderT a (StateT s m) b -> P.Pipe a b (t m) r
+rsPipe m = forever $ do
+    a <- P.await
+    s <- get
+    -- This is the only line that is different between the Strict and Lazy version
+    ~(c, s') <- lift . lift $ runStateT (runReaderT m a) s
+    put s'
+    P.yield c
+{-# INLINABLE rsPipe #-}
+
+-- | Convert a 'Pipes.Concurrent.Input' and a 'Glazier.Gadget' into a stateful 'Pipes.Producer' of commands to interpret.
+rsProducer ::
+  (MonadState s (t STM), MonadTrans t) =>
+  PC.Input a -> ReaderT a (StateT s STM) c -> P.Producer' c (t STM) ()
+rsProducer input m = hoist lift (PM.fromInputSTM input) P.>-> rsPipe m
+{-# INLINABLE rsProducer #-}
diff --git a/src/Pipes/Misc/State/Strict.hs b/src/Pipes/Misc/State/Strict.hs
--- a/src/Pipes/Misc/State/Strict.hs
+++ b/src/Pipes/Misc/State/Strict.hs
@@ -2,9 +2,14 @@
 
 module Pipes.Misc.State.Strict where
 
+import Control.Concurrent.STM
 import Control.Lens
+import Control.Monad.Morph
+import Control.Monad.Reader
 import Control.Monad.State.Strict
 import qualified Pipes as P
+import qualified Pipes.Concurrent as PC
+import qualified Pipes.Misc.Concurrent as PM
 import qualified Pipes.Prelude as PP
 
 -- | Store the output of the pipe into a MonadState.
@@ -38,3 +43,21 @@
     f s
     pure a
 {-# INLINABLE onState #-}
+
+-- | Converts a 'Glazier.Gadget' into a 'Pipes.Pipe'
+rsPipe :: (Monad m, MonadTrans t, MonadState s (t m)) => ReaderT a (StateT s m) b -> P.Pipe a b (t m) r
+rsPipe m = forever $ do
+    a <- P.await
+    s <- get
+    -- This is the only line that is different between the Strict and Lazy version
+    (c, s') <- lift . lift $ runStateT (runReaderT m a) s
+    put s'
+    P.yield c
+{-# INLINABLE rsPipe #-}
+
+-- | Convert a 'Pipes.Concurrent.Input' and a 'Glazier.Gadget' into a stateful 'Pipes.Producer' of commands to interpret.
+rsProducer ::
+  (MonadState s (t STM), MonadTrans t) =>
+  PC.Input a -> ReaderT a (StateT s STM) b -> P.Producer' b (t STM) ()
+rsProducer input m = hoist lift (PM.fromInputSTM input) P.>-> rsPipe m
+{-# INLINABLE rsProducer #-}
