diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2013, Maksymilian Owsianny
+
+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 Maksymilian Owsianny 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
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,6 @@
+module Main (main) where
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
diff --git a/src/Control/Concurrent/STM/Lifted.hs b/src/Control/Concurrent/STM/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/Lifted.hs
@@ -0,0 +1,9 @@
+module Control.Concurrent.STM.Lifted (module All) where
+
+import Control.Concurrent.STM.TVar.Lifted    as All
+import Control.Concurrent.STM.TChan.Lifted   as All
+import Control.Concurrent.STM.TMVar.Lifted   as All
+import Control.Concurrent.STM.TQueue.Lifted  as All
+import Control.Concurrent.STM.TBQueue.Lifted as All
+import Internal                             as All (STM, atomically)
+
diff --git a/src/Control/Concurrent/STM/TBQueue/Lifted.hs b/src/Control/Concurrent/STM/TBQueue/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/TBQueue/Lifted.hs
@@ -0,0 +1,42 @@
+module Control.Concurrent.STM.TBQueue.Lifted
+    ( module All
+	, newTBQueueIO
+	, readTBQueueIO
+	, tryReadTBQueueIO
+	, peekTBQueueIO
+	, tryPeekTBQueueIO
+	, writeTBQueueIO
+    , unGetTBQueueIO
+    , isEmptyTBQueueIO
+    ) where
+
+import Control.Concurrent.STM.TBQueue as All hiding (newTBQueueIO)
+import qualified Control.Concurrent.STM.TBQueue as STM
+import Internal
+
+----------------------------------------------------------------------
+
+
+newTBQueueIO :: MonadIO m => Int -> m (TBQueue a)
+newTBQueueIO = liftIO . STM.newTBQueueIO
+
+writeTBQueueIO :: MonadIO m => TBQueue a -> a -> m ()
+writeTBQueueIO = atomically .: writeTBQueue
+
+readTBQueueIO :: MonadIO m => TBQueue a -> m a
+readTBQueueIO = atomically . readTBQueue
+
+tryReadTBQueueIO :: MonadIO m => TBQueue a -> m (Maybe a)
+tryReadTBQueueIO = atomically . tryReadTBQueue
+
+peekTBQueueIO :: MonadIO m => TBQueue a -> m a
+peekTBQueueIO = atomically . peekTBQueue
+
+tryPeekTBQueueIO :: MonadIO m => TBQueue a -> m (Maybe a)
+tryPeekTBQueueIO = atomically . tryPeekTBQueue
+
+unGetTBQueueIO :: MonadIO m => TBQueue a -> a -> m ()
+unGetTBQueueIO = atomically .: unGetTBQueue
+
+isEmptyTBQueueIO :: MonadIO m => TBQueue a -> m Bool
+isEmptyTBQueueIO = atomically . isEmptyTBQueue
diff --git a/src/Control/Concurrent/STM/TChan/Lifted.hs b/src/Control/Concurrent/STM/TChan/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/TChan/Lifted.hs
@@ -0,0 +1,53 @@
+module Control.Concurrent.STM.TChan.Lifted
+    ( module All
+	, newTChanIO
+	, newBroadcastTChanIO
+    , dupTChanIO
+	, readTChanIO
+	, tryReadTChanIO
+	, peekTChanIO
+	, tryPeekTChanIO
+	, writeTChanIO
+    , unGetTChanIO
+    , isEmptyTChanIO
+    , cloneTChanIO
+    ) where
+
+
+import Control.Concurrent.STM.TChan as All
+    hiding (newTChanIO, newBroadcastTChanIO)
+import qualified Control.Concurrent.STM.TChan as STM
+import Internal
+
+newTChanIO :: MonadIO m => m (TChan a)
+newTChanIO = liftIO STM.newTChanIO
+
+newBroadcastTChanIO :: MonadIO m => m (TChan a)
+newBroadcastTChanIO = liftIO STM.newBroadcastTChanIO
+
+dupTChanIO :: MonadIO m => TChan a -> m (TChan a)
+dupTChanIO = atomically . dupTChan
+
+readTChanIO :: MonadIO m => TChan a -> m a
+readTChanIO = atomically . readTChan
+
+tryReadTChanIO :: MonadIO m => TChan a -> m (Maybe a)
+tryReadTChanIO = atomically . tryReadTChan
+
+peekTChanIO :: MonadIO m => TChan a -> m a
+peekTChanIO = atomically . peekTChan
+
+tryPeekTChanIO :: MonadIO m => TChan a -> m (Maybe a)
+tryPeekTChanIO = atomically . tryPeekTChan
+
+writeTChanIO :: MonadIO m => TChan a -> a -> m ()
+writeTChanIO = atomically .: writeTChan
+
+unGetTChanIO :: MonadIO m => TChan a -> a -> m ()
+unGetTChanIO = atomically .: unGetTChan
+
+isEmptyTChanIO :: MonadIO m => TChan a -> m Bool
+isEmptyTChanIO = atomically . isEmptyTChan
+
+cloneTChanIO :: MonadIO m => TChan a -> m (TChan a)
+cloneTChanIO = atomically . cloneTChan
diff --git a/src/Control/Concurrent/STM/TMVar/Lifted.hs b/src/Control/Concurrent/STM/TMVar/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/TMVar/Lifted.hs
@@ -0,0 +1,50 @@
+module Control.Concurrent.STM.TMVar.Lifted
+	( module All
+    , newTMVarIO
+	, newEmptyTMVarIO
+	, takeTMVarIO
+	, putTMVarIO
+	, readTMVarIO
+	, tryReadTMVarIO
+	, swapTMVarIO
+	, tryTakeTMVarIO
+	, tryPutTMVarIO
+	, isEmptyTMVarIO
+    ) where
+
+import Control.Concurrent.STM.TMVar as All
+    hiding (newTMVarIO, newEmptyTMVarIO)
+import qualified Control.Concurrent.STM.TMVar as STM
+import Internal
+
+----------------------------------------------------------------------
+
+newTMVarIO :: MonadIO m => a -> m (TMVar a)
+newTMVarIO = liftIO . STM.newTMVarIO
+
+newEmptyTMVarIO :: MonadIO m => m (TMVar a)
+newEmptyTMVarIO = liftIO STM.newEmptyTMVarIO
+
+takeTMVarIO :: MonadIO m => TMVar a -> m a
+takeTMVarIO = atomically . takeTMVar
+
+tryTakeTMVarIO :: MonadIO m => TMVar a -> m (Maybe a)
+tryTakeTMVarIO = atomically . tryTakeTMVar
+
+putTMVarIO :: MonadIO m => TMVar a -> a -> m ()
+putTMVarIO = atomically .: putTMVar
+
+tryPutTMVarIO :: MonadIO m => TMVar a -> a -> m Bool
+tryPutTMVarIO = atomically .: tryPutTMVar
+
+readTMVarIO :: MonadIO m => TMVar a -> m a
+readTMVarIO = atomically . readTMVar
+
+tryReadTMVarIO :: MonadIO m => TMVar a -> m (Maybe a)
+tryReadTMVarIO = atomically . tryReadTMVar
+
+swapTMVarIO :: MonadIO m => TMVar a -> a -> m a
+swapTMVarIO = atomically .: swapTMVar
+
+isEmptyTMVarIO :: MonadIO m => TMVar a -> m Bool
+isEmptyTMVarIO = atomically . isEmptyTMVar
diff --git a/src/Control/Concurrent/STM/TQueue/Lifted.hs b/src/Control/Concurrent/STM/TQueue/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/TQueue/Lifted.hs
@@ -0,0 +1,41 @@
+module Control.Concurrent.STM.TQueue.Lifted
+    ( module All
+	, newTQueueIO
+	, readTQueueIO
+	, tryReadTQueueIO
+	, peekTQueueIO
+	, tryPeekTQueueIO
+	, writeTQueueIO
+    , unGetTQueueIO
+    , isEmptyTQueueIO
+    ) where
+
+import Control.Concurrent.STM.TQueue as All hiding (newTQueueIO)
+import qualified Control.Concurrent.STM.TQueue as STM
+import Internal
+
+----------------------------------------------------------------------
+
+newTQueueIO :: MonadIO m => m (TQueue a)
+newTQueueIO = liftIO STM.newTQueueIO
+
+writeTQueueIO :: MonadIO m => TQueue a -> a -> m ()
+writeTQueueIO = atomically .: writeTQueue
+
+readTQueueIO :: MonadIO m => TQueue a -> m a
+readTQueueIO = atomically . readTQueue
+
+tryReadTQueueIO :: MonadIO m => TQueue a -> m (Maybe a)
+tryReadTQueueIO = atomically . tryReadTQueue
+
+peekTQueueIO :: MonadIO m => TQueue a -> m a
+peekTQueueIO = atomically . peekTQueue
+
+tryPeekTQueueIO :: MonadIO m => TQueue a -> m (Maybe a)
+tryPeekTQueueIO = atomically . tryPeekTQueue
+
+unGetTQueueIO :: MonadIO m => TQueue a -> a -> m ()
+unGetTQueueIO = atomically .: unGetTQueue
+
+isEmptyTQueueIO :: MonadIO m => TQueue a -> m Bool
+isEmptyTQueueIO = atomically . isEmptyTQueue
diff --git a/src/Control/Concurrent/STM/TSem/Lifted.hs b/src/Control/Concurrent/STM/TSem/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/TSem/Lifted.hs
@@ -0,0 +1,21 @@
+module Control.Concurrent.STM.TSem.Lifted
+    ( module All
+    , newTSemIO
+    , waitTSemIO
+    , signalTSemIO
+    ) where
+
+import Control.Concurrent.STM.TSem as All
+import Internal
+
+----------------------------------------------------------------------
+
+newTSemIO :: MonadIO m => Int -> m TSem
+newTSemIO = atomically . newTSem
+
+waitTSemIO :: MonadIO m => TSem -> m ()
+waitTSemIO = atomically . waitTSem
+
+signalTSemIO :: MonadIO m => TSem -> m ()
+signalTSemIO = atomically . signalTSem
+
diff --git a/src/Control/Concurrent/STM/TVar/Lifted.hs b/src/Control/Concurrent/STM/TVar/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/TVar/Lifted.hs
@@ -0,0 +1,37 @@
+module Control.Concurrent.STM.TVar.Lifted
+    ( module All
+    , newTVarIO
+    , readTVarIO
+    , writeTVarIO
+    , modifyTVarIO
+    , modifyTVarIO'
+    , swapTVarIO
+    ) where
+
+import Control.Concurrent.STM.TVar as All
+    hiding (newTVarIO, readTVarIO)
+import qualified Control.Concurrent.STM.TVar as STM
+import Internal
+
+----------------------------------------------------------------------
+
+newTVarIO :: MonadIO m => a -> m (TVar a)
+newTVarIO = liftIO . STM.newTVarIO
+
+readTVarIO :: MonadIO m => TVar a -> m a
+readTVarIO = liftIO . STM.readTVarIO
+
+writeTVarIO :: MonadIO m => TVar a -> a -> m ()
+writeTVarIO = atomically .: writeTVar
+
+-- | Non-strict version
+modifyTVarIO :: MonadIO m => TVar a -> (a -> a) -> m ()
+modifyTVarIO = atomically .: modifyTVar
+
+-- | Strict version
+modifyTVarIO' :: MonadIO m => TVar a -> (a -> a) -> m ()
+modifyTVarIO' = atomically .: modifyTVar'
+
+swapTVarIO :: MonadIO m => TVar a -> a -> m a
+swapTVarIO = atomically .: swapTVar
+
diff --git a/src/Internal.hs b/src/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Internal.hs
@@ -0,0 +1,12 @@
+module Internal (STM, atomically, (.:), MonadIO(..)) where
+
+import Control.Monad.IO.Class
+import Control.Concurrent.STM (STM)
+import qualified Control.Concurrent.STM as STM
+
+(.:) :: (a -> b) -> (c -> d -> a) -> (c -> d -> b)
+(.:) = (.) . (.)
+infixl 8 .:
+
+atomically :: MonadIO m => STM a -> m a
+atomically = liftIO . STM.atomically
diff --git a/stm-lifted.cabal b/stm-lifted.cabal
new file mode 100644
--- /dev/null
+++ b/stm-lifted.cabal
@@ -0,0 +1,40 @@
+name:		stm-lifted
+version:        0.1.0.0
+synopsis:	Software Transactional Memory lifted to MonadIO
+license:	BSD3
+license-file:	LICENSE
+author:         Maksymilian Owsianny
+maintainer:	Maksymilian.Owsianny@gmail.com
+bug-reports:    https://github.com/MaxOw/stm-lifted/issues
+Copyright:      (c) 2013 Maksymilian Owsianny
+category:       Concurrency, MonadIO
+build-type:     Simple
+stability:      Experimental
+cabal-version:  >= 1.10
+
+description:
+ A MonadIO version of
+ <http://hackage.haskell.org/package/stm-2.4.2 STM> library.
+
+
+source-repository head
+    type:     git
+    location: https://github.org/MaxOw/stm-lifted.git
+
+library
+  default-language: Haskell2010
+  hs-source-dirs: src
+  exposed-modules:
+      Control.Concurrent.STM.Lifted
+    , Control.Concurrent.STM.TVar.Lifted
+    , Control.Concurrent.STM.TChan.Lifted
+    , Control.Concurrent.STM.TMVar.Lifted
+    , Control.Concurrent.STM.TQueue.Lifted
+    , Control.Concurrent.STM.TBQueue.Lifted
+    , Control.Concurrent.STM.TSem.Lifted
+  other-modules: Internal
+  build-depends:
+      base          >= 4.5   && < 5
+    , transformers  >= 0.2   && < 0.4
+    , stm           >= 2.4.2 && < 3
+
