diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,30 +1,30 @@
-Copyright Author name here (c) 2016
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of Author name here nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+Copyright Author name here (c) 2016
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,2 @@
-import Distribution.Simple
-main = defaultMain
+import Distribution.Simple
+main = defaultMain
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -1,24 +1,24 @@
-{-# LANGUAGE FlexibleContexts, TypeApplications #-}
-import Interlude
-
-import GHC.IO.Encoding (setLocaleEncoding, utf16)
-import Control.Effects
-import Control.Effects.State hiding (mtlSimple, effectsSimple)
-
-import Criterion.Main
-
-mtlSimple :: MonadState Int m => m ()
-mtlSimple = replicateM_ 1000000 mtlSimple'
-    where mtlSimple' = modify' (+ 1)
-
-effectsSimple :: (MonadEffect (GetState Int) m, MonadEffect (SetState Int) m) => m ()
-effectsSimple = replicateM_ 1000000 effectsSimple'
-    where effectsSimple' = modifyState (+ (1 :: Int))
-
-main :: IO ()
-main =
-    defaultMain
-        [ bench "MTL state" $ nfIO (execStateT mtlSimple 0)
-        , bench "Effects state" $ nfIO effState
-        ]
-    where effState = handleStateIO @_ @Int @Int 0 (effectsSimple >> getState)
+{-# LANGUAGE FlexibleContexts, TypeApplications #-}
+import Interlude
+
+import GHC.IO.Encoding (setLocaleEncoding, utf16)
+import Control.Effects
+import Control.Effects.State hiding (mtlSimple, effectsSimple)
+
+import Criterion.Main
+
+mtlSimple :: MonadState Int m => m ()
+mtlSimple = replicateM_ 1000000 mtlSimple'
+    where mtlSimple' = modify' (+ 1)
+
+effectsSimple :: (MonadEffect (GetState Int) m, MonadEffect (SetState Int) m) => m ()
+effectsSimple = replicateM_ 1000000 effectsSimple'
+    where effectsSimple' = modifyState (+ (1 :: Int))
+
+main :: IO ()
+main =
+    defaultMain
+        [ bench "MTL state" $ nfIO (execStateT mtlSimple 0)
+        , bench "Effects state" $ nfIO effState
+        ]
+    where effState = handleStateIO @_ @Int @Int 0 (effectsSimple >> getState)
diff --git a/simple-effects.cabal b/simple-effects.cabal
--- a/simple-effects.cabal
+++ b/simple-effects.cabal
@@ -1,44 +1,45 @@
-name:                simple-effects
-version:             0.3.0.1    
-synopsis:            A simple effect system that integrates with MTL
-description:         Please see README.md
-homepage:            https://gitlab.com/LukaHorvat/simple-effects
-license:             BSD3
-license-file:        LICENSE
-author:              Luka Horvat
-maintainer:          luka.horvat9@gmail.com
-copyright:           2016 Luka Horvat
-category:            Control
-build-type:          Simple
-cabal-version:       >=1.10
-
-library
-  exposed-modules:     Control.Effects
-                     , Control.Effects1
-                     , Control.Effects.State
-                     , Control.Effects.Reader
-                     , Control.Effects.List
-  hs-source-dirs:      src
-  default-language:    Haskell2010
-  build-depends:       base >= 4.7 && < 5
-                     , transformers
-                     , mtl
-                     , interlude-l >= 0.1.0.6
-                     , monad-control == 1.0.*
-                     , transformers-base == 0.4.*
-                     , list-t
-                     , lens
-  default-extensions:  NoImplicitPrelude
-
-benchmark bench-effects
-  type:                exitcode-stdio-1.0
-  hs-source-dirs:      bench
-  main-is:             Bench.hs
-  build-depends:       base
-                     , criterion
-                     , mtl
-                     , transformers
-                     , interlude-l
-                     , lens
-                     , simple-effects
-  default-language:    Haskell2010
+name:                simple-effects
+version:             0.3.0.2
+synopsis:            A simple effect system that integrates with MTL
+description:         Please see README.md
+homepage:            https://gitlab.com/LukaHorvat/simple-effects
+license:             BSD3
+license-file:        LICENSE
+author:              Luka Horvat
+maintainer:          luka.horvat9@gmail.com
+copyright:           2016 Luka Horvat
+category:            Control
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Control.Effects
+                     , Control.Effects1
+                     , Control.Effects.State
+                     , Control.Effects.Reader
+                     , Control.Effects.List
+                     , Control.Effects.Signal
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+  build-depends:       base >= 4.7 && < 5
+                     , transformers
+                     , mtl
+                     , interlude-l >= 0.1.0.6
+                     , monad-control == 1.0.*
+                     , transformers-base == 0.4.*
+                     , list-t
+                     , lens
+  default-extensions:  NoImplicitPrelude
+
+benchmark bench-effects
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      bench
+  main-is:             Bench.hs
+  build-depends:       base
+                     , criterion
+                     , mtl
+                     , transformers
+                     , interlude-l
+                     , lens
+                     , simple-effects
+  default-language:    Haskell2010
diff --git a/src/Control/Effects.hs b/src/Control/Effects.hs
--- a/src/Control/Effects.hs
+++ b/src/Control/Effects.hs
@@ -1,52 +1,52 @@
-{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, DeriveFunctor
-           , GeneralizedNewtypeDeriving, UndecidableInstances, StandaloneDeriving
-           , IncoherentInstances #-}
-module Control.Effects (module Control.Effects, module Control.Effects1) where
-
-import Interlude
-
-import Control.Monad.Reader
-import Control.Monad.Trans.Control
-import Control.Monad.Base
-
-import Control.Effects1
-
-type family EffectMsg eff :: *
-type family EffectRes eff :: *
-
-class Monad m => MonadEffect eff m where
-    -- | Use the effect described by 'eff'.
-    effect :: proxy eff -> EffectMsg eff -> m (EffectRes eff)
-
--- | The 'EffectHandler' is rally just a 'ReaderT' carrying around the function that knows how to
---   handle the effect.
-newtype EffectHandler eff m a = EffectHandler
-    { unpackEffectHandler :: ReaderT (EffectMsg eff -> m (EffectRes eff)) m a }
-    deriving (Functor, Applicative, Monad, MonadState s, MonadIO, MonadCatch, MonadThrow, MonadRandom)
-
-instance MonadTrans (EffectHandler eff) where
-    lift = EffectHandler . lift
-
-instance MonadReader s m => MonadReader s (EffectHandler eff m) where
-    ask = EffectHandler (lift ask)
-    local f (EffectHandler rdr) = EffectHandler (ReaderT $ local f . runReaderT rdr)
-
-deriving instance MonadBase IO m => MonadBase IO (EffectHandler eff m)
-
-instance MonadBaseControl IO m => MonadBaseControl IO (EffectHandler eff m) where
-    type StM (EffectHandler eff m) a = StM (ReaderT (EffectMsg eff -> m (EffectRes eff)) m) a
-    liftBaseWith f = EffectHandler $ liftBaseWith $ \q -> f (q . unpackEffectHandler)
-    restoreM = EffectHandler . restoreM
-
-instance {-# OVERLAPPABLE #-} (MonadEffect eff m, MonadTrans t, Monad (t m))
-         => MonadEffect eff (t m) where
-    {-# INLINE effect #-}
-    effect p msg = lift (effect p msg)
-
-instance Monad m => MonadEffect eff (EffectHandler eff m) where
-    {-# INLINE effect #-}
-    effect _ msg = EffectHandler (ReaderT ($ msg))
-
--- | Handle the effect described by 'eff'.
-handleEffect :: Monad m => (EffectMsg eff -> m (EffectRes eff)) -> EffectHandler eff m a -> m a
-handleEffect f eh = runReaderT (unpackEffectHandler eh) f
+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, DeriveFunctor
+           , GeneralizedNewtypeDeriving, UndecidableInstances, StandaloneDeriving
+           , IncoherentInstances #-}
+module Control.Effects (module Control.Effects, module Control.Effects1) where
+
+import Interlude
+
+import Control.Monad.Reader
+import Control.Monad.Trans.Control
+import Control.Monad.Base
+
+import Control.Effects1
+
+type family EffectMsg eff :: *
+type family EffectRes eff :: *
+
+class Monad m => MonadEffect eff m where
+    -- | Use the effect described by 'eff'.
+    effect :: proxy eff -> EffectMsg eff -> m (EffectRes eff)
+
+-- | The 'EffectHandler' is rally just a 'ReaderT' carrying around the function that knows how to
+--   handle the effect.
+newtype EffectHandler eff m a = EffectHandler
+    { unpackEffectHandler :: ReaderT (EffectMsg eff -> m (EffectRes eff)) m a }
+    deriving (Functor, Applicative, Monad, MonadState s, MonadIO, MonadCatch, MonadThrow, MonadRandom)
+
+instance MonadTrans (EffectHandler eff) where
+    lift = EffectHandler . lift
+
+instance MonadReader s m => MonadReader s (EffectHandler eff m) where
+    ask = EffectHandler (lift ask)
+    local f (EffectHandler rdr) = EffectHandler (ReaderT $ local f . runReaderT rdr)
+
+deriving instance MonadBase IO m => MonadBase IO (EffectHandler eff m)
+
+instance MonadBaseControl IO m => MonadBaseControl IO (EffectHandler eff m) where
+    type StM (EffectHandler eff m) a = StM (ReaderT (EffectMsg eff -> m (EffectRes eff)) m) a
+    liftBaseWith f = EffectHandler $ liftBaseWith $ \q -> f (q . unpackEffectHandler)
+    restoreM = EffectHandler . restoreM
+
+instance {-# OVERLAPPABLE #-} (MonadEffect eff m, MonadTrans t, Monad (t m))
+         => MonadEffect eff (t m) where
+    {-# INLINE effect #-}
+    effect p msg = lift (effect p msg)
+
+instance Monad m => MonadEffect eff (EffectHandler eff m) where
+    {-# INLINE effect #-}
+    effect _ msg = EffectHandler (ReaderT ($ msg))
+
+-- | Handle the effect described by 'eff'.
+handleEffect :: Monad m => (EffectMsg eff -> m (EffectRes eff)) -> EffectHandler eff m a -> m a
+handleEffect f eh = runReaderT (unpackEffectHandler eh) f
diff --git a/src/Control/Effects/Reader.hs b/src/Control/Effects/Reader.hs
--- a/src/Control/Effects/Reader.hs
+++ b/src/Control/Effects/Reader.hs
@@ -1,22 +1,22 @@
-{-# LANGUAGE ScopedTypeVariables, TypeFamilies, FlexibleContexts #-}
-module Control.Effects.Reader (module Control.Effects.Reader, module Control.Effects) where
-
-import Interlude
-
-import Control.Lens
-
-import Control.Effects
-
-data ReadEnv e
-
-type instance EffectMsg (ReadEnv e) = ()
-type instance EffectRes (ReadEnv e) = e
-
-readEnv :: forall m e. MonadEffect (ReadEnv e) m => m e
-readEnv = effect (Proxy :: Proxy (ReadEnv e)) ()
-
-handleReadEnv :: Monad m => m e -> EffectHandler (ReadEnv e) m a -> m a
-handleReadEnv = handleEffect . const
-
-handleSubreader :: MonadEffect (ReadEnv e) m => (e -> e') -> EffectHandler (ReadEnv e') m a -> m a
-handleSubreader f = handleReadEnv (f <$> readEnv)
+{-# LANGUAGE ScopedTypeVariables, TypeFamilies, FlexibleContexts #-}
+module Control.Effects.Reader (module Control.Effects.Reader, module Control.Effects) where
+
+import Interlude
+
+import Control.Lens
+
+import Control.Effects
+
+data ReadEnv e
+
+type instance EffectMsg (ReadEnv e) = ()
+type instance EffectRes (ReadEnv e) = e
+
+readEnv :: forall m e. MonadEffect (ReadEnv e) m => m e
+readEnv = effect (Proxy :: Proxy (ReadEnv e)) ()
+
+handleReadEnv :: Monad m => m e -> EffectHandler (ReadEnv e) m a -> m a
+handleReadEnv = handleEffect . const
+
+handleSubreader :: MonadEffect (ReadEnv e) m => (e -> e') -> EffectHandler (ReadEnv e') m a -> m a
+handleSubreader f = handleReadEnv (f <$> readEnv)
diff --git a/src/Control/Effects/Signal.hs b/src/Control/Effects/Signal.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Effects/Signal.hs
@@ -0,0 +1,67 @@
+{-# LANGUAGE TypeFamilies, ScopedTypeVariables, FlexibleContexts, Rank2Types, ConstraintKinds #-}
+{-# LANGUAGE DeriveAnyClass, OverloadedStrings, MultiParamTypeClasses, FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
+module Control.Effects.Signal
+    ( MonadEffectSignal(..), ResumeOrBreak(..), throwSignal, handleSignal, handleAsException
+    , module Control.Effects ) where
+
+import Interlude
+import Prelude (Show(..))
+
+import Control.Effects
+
+data Signal a b
+type instance EffectMsg (Signal a b) = a
+type instance EffectRes (Signal a b) = b
+
+-- | This class allows you to "throw" a signal. For the most part signals are the same as checked
+--   exceptions. The difference here is that the handler has the option to provide the value that
+--   will be the result _of calling the signal function_. This effectibvely allows you to have
+--   recoverable exceptions at the call site, instead of just at the handling site.
+--
+--   This class can be considered an alias for @MonadEffect (Signal a b)@ so your code isn't
+--   required to provide any instances.
+class MonadEffect (Signal a b) m => MonadEffectSignal a b m | m a -> b where
+    -- | There are no restrictions on the type of values that can be thrown or returned.
+    signal :: a -> m b
+    signal = effect (Proxy :: Proxy (Signal a b))
+
+instance Monad m => MonadEffectSignal a b (EffectHandler (Signal a b) m)
+instance {-# OVERLAPPABLE #-} (MonadEffectSignal a b m, MonadTrans t, Monad (t m))
+         => MonadEffectSignal a b (t m)
+
+-- | The handle function will return a value of this type.
+data ResumeOrBreak b c = Resume b -- ^ Give a value to the caller of @signal@ and keep going.
+                       | Break c -- ^ Continue the execution after the handler. The handler will
+                                 --   return this value
+
+data NoResume a = NoResume a deriving (Eq, Ord)
+instance Show (NoResume a) where
+    show = const "NoResume"
+instance Typeable a => Exception (NoResume a)
+
+-- | Throw a signal with no possible recovery. The handler is forced to only return the @Break@
+--   constructor because it cannot construct a @Void@ value.
+--
+--   If this function is used along with @handleAsException@, this module behaves like regular
+--   checked exceptions.
+throwSignal :: MonadEffectSignal a Void m => a -> m b
+throwSignal = fmap absurd . signal
+
+-- | Handle signals of a computation. The handler function has the option to provide a value
+--   to the caller of @signal@ and continue execution there, or do what regular exception handlers
+--   do and continue execution after the handler.
+handleSignal :: (MonadCatch m, Typeable c)
+             => (a -> m (ResumeOrBreak b c)) -> EffectHandler (Signal a b) m c -> m c
+handleSignal f a =
+    handle (\(NoResume c) -> return c) $ handleEffect (\s -> do
+        rb <- f s
+        case rb of
+            Resume b -> return b
+            Break c -> throwM (NoResume c)) a
+
+-- | This handler can only behave like a regular exception handler. If used along with @throwSignal@
+--   this module behaves like regular checked exceptions.
+handleAsException :: (MonadCatch m, Typeable c)
+                => (a -> m c) -> EffectHandler (Signal a b) m c -> m c
+handleAsException f = handleSignal (fmap Break . f)
diff --git a/src/Control/Effects/State.hs b/src/Control/Effects/State.hs
--- a/src/Control/Effects/State.hs
+++ b/src/Control/Effects/State.hs
@@ -1,65 +1,65 @@
-{-# LANGUAGE TypeFamilies, ScopedTypeVariables, FlexibleContexts, Rank2Types, ConstraintKinds #-}
-module Control.Effects.State (module Control.Effects.State, module Control.Effects) where
-
-import Interlude
-
-import Data.IORef
-import Control.Lens
-
-import Control.Effects
-
-data GetState s
-data SetState s
-
-type instance EffectMsg (GetState s) = ()
-type instance EffectRes (GetState s) = s
-
-type instance EffectMsg (SetState s) = s
-type instance EffectRes (SetState s) = ()
-
-type MonadEffectState s m = (MonadEffect (GetState s) m, MonadEffect (SetState s) m)
-type EffectHandlerState s m = EffectHandler (GetState s) (EffectHandler (SetState s) m)
-
-{-# INLINE getState #-}
-getState :: forall s m. MonadEffect (GetState s) m => m s
-getState = effect (Proxy :: Proxy (GetState s)) ()
-
-{-# INLINE setState #-}
-setState :: forall s m. MonadEffect (SetState s) m => s -> m ()
-setState = effect (Proxy :: Proxy (SetState s))
-
-{-# INLINE modifyState #-}
-modifyState :: forall s m. MonadEffectState s m => (s -> s) -> m ()
-modifyState f = setState . f =<< getState
-
-{-# INLINE handleGetState #-}
-handleGetState :: Monad m => m s -> EffectHandler (GetState s) m a -> m a
-handleGetState = handleEffect . const
-
-{-# INLINE handleSetState #-}
-handleSetState :: Monad m => (s -> m ()) -> EffectHandler (SetState s) m a -> m a
-handleSetState = handleEffect
-
-{-# INLINE handleState #-}
-handleState :: Monad m => m s -> (s -> m ()) -> EffectHandlerState s m a -> m a
-handleState getter setter = handleSetState setter . handleGetState (lift getter)
-
-handleStateIO :: MonadIO m => s -> EffectHandlerState s m a -> m a
-handleStateIO initial m = do
-    ref <- liftIO (newIORef initial)
-    m & handleState (liftIO (readIORef  ref)) (liftIO . writeIORef ref)
-
-{-# INLINE handleStateT #-}
-handleStateT :: Monad m => s -> EffectHandlerState s (StateT s m) a -> m a
-handleStateT initial m = evalStateT (handleSetState put $ handleGetState get m) initial
-
-handleSubstate :: MonadEffectState s m => Lens' s t -> t -> EffectHandlerState t m a -> m a
-handleSubstate lensST initial m = do
-    oldState <- getState
-    setState (set lensST initial oldState)
-    res <- m & handleGetState (view lensST <$> getState)
-             & handleSetState (\s -> do
-                 oldState <- getState
-                 setState (oldState & lensST .~ s))
-    setState oldState
-    return res
+{-# LANGUAGE TypeFamilies, ScopedTypeVariables, FlexibleContexts, Rank2Types, ConstraintKinds #-}
+module Control.Effects.State (module Control.Effects.State, module Control.Effects) where
+
+import Interlude
+
+import Data.IORef
+import Control.Lens
+
+import Control.Effects
+
+data GetState s
+data SetState s
+
+type instance EffectMsg (GetState s) = ()
+type instance EffectRes (GetState s) = s
+
+type instance EffectMsg (SetState s) = s
+type instance EffectRes (SetState s) = ()
+
+type MonadEffectState s m = (MonadEffect (GetState s) m, MonadEffect (SetState s) m)
+type EffectHandlerState s m = EffectHandler (GetState s) (EffectHandler (SetState s) m)
+
+{-# INLINE getState #-}
+getState :: forall s m. MonadEffect (GetState s) m => m s
+getState = effect (Proxy :: Proxy (GetState s)) ()
+
+{-# INLINE setState #-}
+setState :: forall s m. MonadEffect (SetState s) m => s -> m ()
+setState = effect (Proxy :: Proxy (SetState s))
+
+{-# INLINE modifyState #-}
+modifyState :: forall s m. MonadEffectState s m => (s -> s) -> m ()
+modifyState f = setState . f =<< getState
+
+{-# INLINE handleGetState #-}
+handleGetState :: Monad m => m s -> EffectHandler (GetState s) m a -> m a
+handleGetState = handleEffect . const
+
+{-# INLINE handleSetState #-}
+handleSetState :: Monad m => (s -> m ()) -> EffectHandler (SetState s) m a -> m a
+handleSetState = handleEffect
+
+{-# INLINE handleState #-}
+handleState :: Monad m => m s -> (s -> m ()) -> EffectHandlerState s m a -> m a
+handleState getter setter = handleSetState setter . handleGetState (lift getter)
+
+handleStateIO :: MonadIO m => s -> EffectHandlerState s m a -> m a
+handleStateIO initial m = do
+    ref <- liftIO (newIORef initial)
+    m & handleState (liftIO (readIORef  ref)) (liftIO . writeIORef ref)
+
+{-# INLINE handleStateT #-}
+handleStateT :: Monad m => s -> EffectHandlerState s (StateT s m) a -> m a
+handleStateT initial m = evalStateT (handleSetState put $ handleGetState get m) initial
+
+handleSubstate :: MonadEffectState s m => Lens' s t -> t -> EffectHandlerState t m a -> m a
+handleSubstate lensST initial m = do
+    oldState <- getState
+    setState (set lensST initial oldState)
+    res <- m & handleGetState (view lensST <$> getState)
+             & handleSetState (\s -> do
+                 oldState <- getState
+                 setState (oldState & lensST .~ s))
+    setState oldState
+    return res
