diff --git a/COPYING b/COPYING
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,25 @@
+Copyright (c) 2012 Boris Sukholitko
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. 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.
+3. The names of the authors may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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/Control/Monad/Trans/State/Plus.hs b/Control/Monad/Trans/State/Plus.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Trans/State/Plus.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleInstances, MultiParamTypeClasses #-}
+----------------------------------------------------------------------
+-- |
+-- Module      :  Control.Monad.Trans.State.Plus
+-- Copyright   :  (c) Boris Sukholitko 2012
+-- License     :  BSD3
+-- 
+-- Maintainer  :  boriss@gmail.com
+-- Stability   :  experimental
+-- 
+-- MonadPlus with left catch (MonadOr) for StateT.
+----------------------------------------------------------------------
+module Control.Monad.Trans.State.Plus (
+    -- * The StatePlusT monad transformer
+    StatePlusT, runStatePlusT, execStatePlusT, evalStatePlusT) where
+
+import Control.Monad.State
+
+-- | StatePlusT behaves similar to StateT monad transformer
+newtype StatePlusT s m a = MkSPT { unSPT :: StateT (Bool, s) m a }
+                                deriving (Functor, MonadTrans, MonadIO)
+
+mzeroError :: a
+mzeroError = error "StatePlusT mzero value"
+
+instance Monad m => Monad (StatePlusT s m) where
+    return = lift . return
+    x >>= f = (MkSPT . StateT) go
+        where go s = do
+                    (a, s') <- runStateT (unSPT x) s
+                    if fst s'
+                            then runStateT (unSPT $ f a) s'
+                            else return $ (mzeroError, s')
+
+instance Monad m => MonadState s (StatePlusT s m) where
+    get = (MkSPT . StateT) $ \s -> return (snd s, s)
+    put v = (MkSPT . StateT) $ \s -> return ((), (fst s, v))
+
+plusStates :: (a, (Bool, s)) -> (a, (Bool, s)) -> (a, (Bool, s))
+plusStates (_, (False, _)) b = b
+plusStates a _ = a
+
+instance Monad m => MonadPlus (StatePlusT s m) where
+    mzero = (MkSPT . StateT) $ \s -> return (mzeroError, (False, snd s))
+    mplus a b = (MkSPT . StateT) go where
+        go s = do
+            as <- runStateT (unSPT a) s
+            bs <- runStateT (unSPT b) s
+            let (rr, rs) = plusStates as bs
+            runStateT (return rr) rs
+
+-- | Evaluate StatePlusT monad. In difference from runStateT it returns
+-- @Nothing@ if @mzero@ has been encountered. @Just a@ otherwise.
+runStatePlusT :: Monad m => StatePlusT s m a -> s -> m (Maybe a, s)
+runStatePlusT sm s = do
+    (v, (isOK, ss)) <- runStateT (unSPT sm) (True, s)
+    return (if isOK then Just v else Nothing, ss)
+
+-- | Execute StatePlusT monad returning resulting state
+execStatePlusT :: Monad m => StatePlusT s m a -> s -> m s
+execStatePlusT sm s = do
+    (_, ss) <- runStatePlusT sm s
+    return ss
+
+-- | Evaluate StatePlusT monad returning resulting value. See above
+-- for the semantics.
+evalStatePlusT :: Monad m => StatePlusT s m a -> s -> m (Maybe a)
+evalStatePlusT sm s = do
+    (mb, _) <- runStatePlusT sm s
+    return mb
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,5 @@
+module Main where
+
+import Distribution.Simple
+
+main = defaultMain
diff --git a/state-plus.cabal b/state-plus.cabal
new file mode 100644
--- /dev/null
+++ b/state-plus.cabal
@@ -0,0 +1,25 @@
+Name:                state-plus
+Version:             0.1
+License:             BSD3
+License-File:        COPYING
+Copyright:           Boris Sukholitko, 2012
+Author:              Boris Sukholitko
+Maintainer:          boriss@gmail.com
+Cabal-version:       >= 1.8
+Build-type:          Simple
+Synopsis:            MonadPlus for StateT
+Description:         Implements MonadPlus with left catch (MonadOr) for StateT.
+Category:            Control
+
+library 
+  build-depends:  base < 5, mtl
+  ghc-options:      -Wall
+  exposed-modules:  Control.Monad.Trans.State.Plus
+
+test-suite Main
+  type:            exitcode-stdio-1.0
+  build-depends:   base < 5, QuickCheck, mtl, state-plus, checkers
+  ghc-options:     -Wall
+  hs-source-dirs:  tests
+  main-is:         Main.hs
+
diff --git a/tests/Main.hs b/tests/Main.hs
new file mode 100644
--- /dev/null
+++ b/tests/Main.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving #-}
+import Control.Monad.Trans.State.Plus
+import Test.QuickCheck (Arbitrary, arbitrary, CoArbitrary, stdArgs
+                            , Args(maxSuccess), quickCheckWithResult)
+import Test.QuickCheck.Function
+import Control.Monad.Identity
+import Control.Monad.State
+import Test.QuickCheck.Classes
+import Test.QuickCheck.Checkers
+import Test.QuickCheck.Test (isSuccess)
+import Test.QuickCheck.Property (property)
+import Data.List (foldl')
+import System.Exit (exitFailure)
+
+newtype P = P Bool deriving (Eq, Arbitrary, Function, Show, CoArbitrary)
+newtype SI = SI [Int] deriving (Eq, Arbitrary, Function, Show, CoArbitrary)
+instance Show (StatePlusT SI Identity P) where
+    show m = "StatePlus: " ++ show (runIdentity $ runStatePlusT m (SI [0]))
+
+arbSP :: SI -> P -> Bool -> StatePlusT SI Identity P
+arbSP si p b = do
+    put si
+    when b $ mzero
+    return p
+
+instance Arbitrary (StatePlusT SI Identity P) where
+    arbitrary = do
+        s <- arbitrary
+        p <- arbitrary
+        b <- arbitrary
+        return $ arbSP s p b
+
+extract :: StatePlusT SI Identity P -> Maybe (P, SI)
+extract m = case fst res of
+    Nothing -> Nothing
+    Just v -> Just (v, snd res)
+    where res = runIdentity $ runStatePlusT m (SI [0])
+
+instance EqProp (StatePlusT SI Identity P) where
+    a =-= b = property $ (extract a) == (extract b)
+
+-- shamelessly copied from Checkers
+checkB :: TestBatch -> IO ()
+checkB (name,tests) =
+  do putStrLn $ "\n" ++ name ++ ":"
+     mapM_ pr tests
+ where
+   pr (s,p) = do putStr (padTo (width + 4) ("  "++s ++ ":"))
+                 r <- quickCheckWithResult stdArgs { maxSuccess = 500 } p
+                 when (not $ isSuccess r) $ exitFailure
+   width    = foldl' max 0 (map (length.fst) tests)
+   padTo n = take n . (++ repeat ' ')
+
+main :: IO ()
+main = do
+    checkB (monad (undefined :: StatePlusT SI Identity (P, P, P)))
+    checkB (monadOr (undefined :: StatePlusT SI Identity (P, P)))
+
