diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2015 Sam Rijs
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/attoparsec-trans.cabal b/attoparsec-trans.cabal
new file mode 100644
--- /dev/null
+++ b/attoparsec-trans.cabal
@@ -0,0 +1,27 @@
+-- Initial attoparsec-trans.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                attoparsec-trans
+version:             0.1.0.0
+synopsis:            Interleaved effects for attoparsec parsers
+-- description:         
+homepage:            https://github.com/srijs/haskell-attoparsec-trans
+license:             MIT
+license-file:        LICENSE
+author:              Sam Rijs
+maintainer:          srijs@airpost.net
+-- copyright:           
+category:            Control
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Control.Monad.Trans.Parser
+  -- other-modules:       
+  -- other-extensions:    
+  build-depends:       base >=4.7 && <4.8,
+                       transformers >=0.3 && <0.4,
+                       attoparsec >=0.12 && <0.14
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Control/Monad/Trans/Parser.hs b/src/Control/Monad/Trans/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/Trans/Parser.hs
@@ -0,0 +1,105 @@
+module Control.Monad.Trans.Parser
+  (
+  -- * Parser types
+   ResultM(..), toM
+  , ParserT(..), liftIR, liftP
+  -- * Running parsers
+  , feedM, feedMWith
+  , runParserTOnly
+  , runParserTWith
+  -- ** Result conversion
+  , failResultM
+  , zeroResultM
+  , maybeResultM
+  , eitherResultM
+  ,) where
+
+import Data.Attoparsec.Combinator (feed)
+import Data.Attoparsec.Internal.Types (IResult(..))
+import Data.Monoid (Monoid, mempty, (<>))
+
+import Control.Applicative (Applicative, pure, (<*>))
+import Control.Monad (MonadPlus, mzero, ap)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import Control.Monad.Trans.Class (MonadTrans, lift)
+
+-- * Parser Types
+
+data ResultM i m r
+  = FailM i String
+  | DoneM i r
+  | PartialM (ParserT i m r)
+
+instance Monad m => Functor (ResultM i m) where
+  fmap f (FailM i s)  = FailM i s
+  fmap f (DoneM i r)  = DoneM i (f r)
+  fmap f (PartialM p) = PartialM (fmap f p)
+
+toM :: Monad m => IResult i r -> ResultM i m r
+toM (Fail i _ s) = FailM i s
+toM (Done i r)   = DoneM i r
+toM (Partial p)  = PartialM . ParserT $ return . toM . p
+
+newtype ParserT i m r = ParserT { runParserT :: i -> m (ResultM i m r) }
+
+liftP :: Monad m => (i -> IResult i r) -> ParserT i m r
+liftP p = ParserT $ return . toM . p
+
+liftIR :: (Monad m, Monoid i) => IResult i r -> ParserT i m r
+liftIR = liftP . feed
+
+instance Monad m => Functor (ParserT i m) where
+  fmap f mr = pure f <*> mr
+
+instance Monad m => Applicative (ParserT i m) where
+  pure = return
+  (<*>) = ap
+
+instance Monad m => Monad (ParserT i m) where
+  return r = ParserT $ \i -> return (DoneM i r)
+  mr >>= f = ParserT $ \i -> runParserT mr i >>= rec f
+    where
+      rec f (FailM i s)  = return (FailM i s)
+      rec f (DoneM i r)  = runParserT (f r) i
+      rec f (PartialM p) = return . PartialM $ p >>= f
+
+instance MonadTrans (ParserT i) where
+  lift mr = ParserT $ \i -> mr >>= return . DoneM i
+
+instance MonadIO m => MonadIO (ParserT i m) where
+  liftIO io = lift (liftIO io)
+
+-- * Running parsers
+
+feedM :: (Monad m, Monoid i) => ResultM i m r -> i -> m (ResultM i m r)
+feedM (FailM i' s) i = return $ FailM (i' <> i) s
+feedM (DoneM i' r) i = return $ DoneM (i' <> i) r
+feedM (PartialM p) i = runParserT p i
+
+feedMWith :: (Monad m, Monoid i, Eq i) => m i -> ResultM i m r -> m (ResultM i m r)
+feedMWith mi r = mi >>= \i -> case i == mempty of
+  True -> return r
+  _ -> feedM r i >>= feedMWith mi
+
+runParserTOnly :: Monad m => ParserT i m r -> i -> m (Either String r)
+runParserTOnly p i = runParserT p i >>= return . eitherResultM
+
+runParserTWith :: (Monad m, Monoid i, Eq i) => m i -> ParserT i m r -> ParserT i m r
+runParserTWith mi p = ParserT $ \i -> runParserT p i >>= feedMWith mi
+
+-- * Result Conversion
+
+failResultM :: Monad m => ResultM i m r -> m r
+failResultM = either fail return . eitherResultM
+
+zeroResultM :: MonadPlus m => ResultM i m r -> m r
+zeroResultM = maybe mzero return . maybeResultM
+
+maybeResultM :: ResultM i m r -> Maybe r
+maybeResultM (DoneM _ r) = Just r
+maybeResultM _ = Nothing
+
+eitherResultM :: ResultM i m r -> Either String r
+eitherResultM (DoneM _ r)  = Right r
+eitherResultM (FailM _ s)  = Left s
+eitherResultM (PartialM _) = Left "Result: incomplete input"
