diff --git a/Control/Monad/Task.hs b/Control/Monad/Task.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Task.hs
@@ -0,0 +1,35 @@
+{- | 
+
+Task monad transformer can help refactor event and callback heavy
+programs into monads via co-routines. The idea is loosely
+based on /Combining Events And Threads For Scalable Network Services/,
+by Peng Li and Steve Zdancewic, in /PLDI/, 2007.
+(<http://www.cis.upenn.edu/~stevez/papers/abstracts.html#LZ07>), but 
+with deterministic and co-oprative lightweight threads, 
+also known as co-routines, so that the base monad can be anything ranging 
+from IO to state monads, or your favorite monad transformer stack.
+
+Besides, Task monad transformer also provides a simple mechanism to signal
+and watch for events, which allows complex event processing logic to be
+expressed as streamlined monadic co-routines.
+
+Task monad transformer is essentially a ContT, or continuation transformer,
+defined to extract the control flow of monadic programs with co-operative
+multi-threading. After the CPS transformation, the program trace is then
+executed with a simple round-robin scheduler.
+
+-}
+
+module Control.Monad.Task
+  ( -- * MonadTask class
+    MonadTask(..)
+    -- * TaskT monad transformer
+  , TaskT (..)
+    -- * Functions
+  , runTask
+  , orElse
+  ) where
+
+import Control.Monad.Trans.Task
+import Control.Monad.Task.Class
+
diff --git a/Control/Monad/Task/Class.hs b/Control/Monad/Task/Class.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Task/Class.hs
@@ -0,0 +1,102 @@
+-- | The MonadTask class that defines the set of combinators to work with Task monad.
+--
+--   The operations for MonadTask are similar to those of co-routines, with the
+--   addition of watching and signaling events. 
+--
+--   We also define a set of auto lifting for common transformers. Note that we 
+--   purposely leave a case undefined where a state transformer goes on top of 
+--   a task monad, because such an operation is either unsound or has to roll
+--   back the state (see @'Control.Monad.Trans.State.liftCallCC'@). So it's 
+--   recommended to keep TaskT on top of all StateT in a transformer stack.
+
+{-# LANGUAGE UndecidableInstances, 
+             FunctionalDependencies, 
+             MultiParamTypeClasses, 
+             FlexibleInstances #-}
+
+module Control.Monad.Task.Class 
+  ( -- * MonadTask class
+    MonadTask(..)
+  , orElse
+  ) where
+
+import Data.Monoid
+import Control.Monad.Cont
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.List
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.Reader
+import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter
+import qualified Control.Monad.Trans.Writer.Strict as StrictWriter
+import Control.Monad.Trans.Error
+
+-- | @MonadTask@ specifies a task monad @m@ over an event type @e@.
+class Monad m => MonadTask e m | m -> e where
+  -- | @yield@ temporarily suspends current task to let others run. 
+  yield  :: m ()
+  -- | @fork@ spawns a task and runs it immediate until it ends or 
+  --   suspends before returning to current task.
+  fork   :: m a -> m ()
+  -- | @watch@ suspends current task to wait for future events, and will
+  --   resume execution when an event triggers its watching function. 
+  watch  :: (e -> Maybe a) -> m a
+  -- | @signal@ broadcasts an event to all other tasks that are watching,
+  --   and give those who wake up the priority to run.
+  signal :: e -> m ()
+  -- | @exit@ ends all tasks and return immediately.
+  exit   :: m ()
+
+-- | @orElse@ is a helper function for combining two trigger functions 
+--   disjuctively, favoring the first one.
+orElse :: (e -> Maybe a) -> (e -> Maybe b) -> e -> Maybe (Either a b)
+orElse f g x = maybe (fmap Right (g x)) (Just . Left) (f x)
+
+instance (Error e, Monad m, MonadTask a m) => MonadTask a (ErrorT e m) where
+  exit   = lift exit
+  yield  = lift yield
+  fork   = lift . fork . runErrorT 
+  watch  = lift . watch
+  signal = lift . signal
+
+instance (Monad m, MonadTask a m) => MonadTask a (IdentityT m) where
+  exit   = lift exit
+  yield  = lift yield
+  fork   = lift . fork . runIdentityT 
+  watch  = lift . watch
+  signal = lift . signal
+
+instance (Monad m, MonadTask a m) => MonadTask a (ListT m) where
+  exit   = lift exit
+  yield  = lift yield
+  fork   = lift . fork . runListT 
+  watch  = lift . watch
+  signal = lift . signal
+
+instance (Monad m, MonadTask a m) => MonadTask a (MaybeT m) where
+  exit   = lift exit
+  yield  = lift yield
+  fork   = lift . fork . runMaybeT 
+  watch  = lift . watch
+  signal = lift . signal
+
+instance (Monad m, MonadTask a m) => MonadTask a (ReaderT r m) where
+  exit   = lift exit
+  yield  = lift yield
+  fork   = ReaderT . (fork .) . runReaderT 
+  watch  = lift . watch
+  signal = lift . signal
+
+instance (Monoid w, Monad m, MonadTask a m) => MonadTask a (LazyWriter.WriterT w m) where
+  exit   = lift exit
+  yield  = lift yield
+  fork   = lift . fork . LazyWriter.runWriterT 
+  watch  = lift . watch
+  signal = lift . signal
+
+instance (Monoid w, Monad m, MonadTask a m) => MonadTask a (StrictWriter.WriterT w m) where
+  exit   = lift exit
+  yield  = lift yield
+  fork   = lift . fork . StrictWriter.runWriterT 
+  watch  = lift . watch
+  signal = lift . signal
+
diff --git a/Control/Monad/Trans/Task.hs b/Control/Monad/Trans/Task.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Trans/Task.hs
@@ -0,0 +1,93 @@
+{-# LANGUAGE GADTs, 
+             UndecidableInstances, 
+             NoMonomorphismRestriction, 
+             GeneralizedNewtypeDeriving, 
+             MultiParamTypeClasses, 
+             FlexibleInstances #-}
+
+module Control.Monad.Trans.Task 
+  ( -- * Task monad transformer
+    TaskT (..)
+    -- * Trace of a base monad
+  , Trace (..)
+  , runTrace
+    -- * Task functions
+  , taskToTrace
+  , runTask
+  ) where
+
+import Control.Applicative
+import Control.Monad.Reader.Class
+import Control.Monad.State.Class
+import Control.Monad.IO.Class
+import Control.Monad.Trans
+import Control.Monad.Trans.Cont
+import Control.Monad.Task.Class
+import Data.Either (partitionEithers)
+
+-- | A @Trace m e@ represents the control flow of a mult-threaded task monad
+--   defined over a base monad @m@ and event type @e@. 
+data Trace m e where
+  EXIT   :: Trace m e
+  RET    :: Trace m e
+  YIELD  :: m (Trace m e) -> Trace m e
+  FORK   :: m (Trace m e) -> m (Trace m e) -> Trace m e
+  WATCH  :: (e -> Maybe v) -> (v -> m (Trace m e)) -> Trace m e 
+  SIGNAL :: e -> m (Trace m e) -> Trace m e
+
+-- | @runTrace@ runs a trace to its completion in the base monad with a simple 
+--   round-robin scheduler.
+runTrace :: Monad m => m (Trace m e) -> m ()
+runTrace prog = loop [prog] []
+  where
+    loop [] _ = return ()
+    loop (m:ms) ss = m >>= step
+      where
+        step EXIT         = return ()
+        step RET          = loop ms ss
+        step (YIELD t)    = loop (ms ++ [t]) ss
+        step (FORK t1 t2) = loop (t1:t2:ms) ss
+        step (WATCH f g)  = loop ms (WATCH f g : ss)
+        step (SIGNAL e t) = loop (ms' ++ [t] ++ ms) ss'
+          where (ms', ss') = partitionEithers evs
+                evs = [ maybe (Right x) (Left . g) (f e) | x@(WATCH f g) <- ss ]
+
+-- | Task monad transformer.
+newtype TaskT e m a 
+  = TaskT { runTaskT :: ContT (Trace m e) m a }
+  deriving (Functor, Applicative, MonadIO)
+
+-- | @tasktoTrace@ CPS-converts a task monad into a trace in its base monad. 
+taskToTrace :: Monad m => TaskT e m a -> m (Trace m e) 
+taskToTrace (TaskT (ContT f)) = f (\_ -> return RET)
+
+-- | @runTask@ runs a task monad until to its completion, i.e., no more active
+--   tasks to run, or until it exits.
+--
+-- * @'runTask' = 'runTrace' . 'taskToTrace'@
+runTask :: Monad m => TaskT e m a -> m ()
+runTask = runTrace . taskToTrace
+
+instance Monad m => Monad (TaskT e m) where
+  return = TaskT . return
+  (>>=) m f = TaskT $ runTaskT m >>= runTaskT . f
+  fail _ = TaskT $ ContT $ \_ -> return EXIT 
+
+instance MonadTrans (TaskT e) where
+  lift = TaskT . lift
+
+instance MonadReader s m => MonadReader s (TaskT e m) where
+  ask = TaskT ask
+  local f = TaskT . local f . runTaskT 
+
+instance MonadState s m => MonadState s (TaskT e m) where
+  get = TaskT get
+  put = TaskT . put
+
+instance Monad m => MonadTask e (TaskT e m) where
+  exit     = TaskT $ ContT $ \_ -> return EXIT
+  yield    = TaskT $ ContT $ return . YIELD . ($())
+  fork p   = TaskT $ ContT $ return . FORK (taskToTrace p) . ($())
+  watch f  = TaskT $ ContT $ return . WATCH f 
+  signal e = TaskT $ ContT $ return . SIGNAL e . ($())
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2012 Paul H. Liu <paul@thev.net>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would
+   be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+   be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+   distribution.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+monad-task
+==========
+
+Task monad transformer that turns event processing into co-routine programming.
+
+See [Invert the Inversion of Control](http://www.thev.net/PaulLiu/invert-inversion.html) for a tutorial on writing a GLFW/OpenGL application using task monad.
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/monad-task.cabal b/monad-task.cabal
new file mode 100644
--- /dev/null
+++ b/monad-task.cabal
@@ -0,0 +1,37 @@
+name:         monad-task
+version:      0.1.0
+homepage:     http://github.com/ninegua/monad-task
+author:       Paul Liu
+maintainer:   Paul Liu <paul@thev.net>
+stability:    experimental
+category:     Control
+cabal-version: >= 1.6
+build-type:   Simple
+synopsis:     A monad transformer that turns event processing into co-routine programming.
+description:
+    Task monad transformer can help refactor event and callback 
+    heavy programs into monads via co-routines. The idea is loosely
+    based on /Combining Events And Threads For Scalable Network Services/,
+    by Peng Li and Steve Zdancewic, in /PLDI/, 2007.
+    (<http://www.cis.upenn.edu/~stevez/papers/abstracts.html#LZ07>), but 
+    with deterministic and co-oprative lightweight threads, also known as 
+    co-routines, so that the base monad can be anything ranging from IO 
+    to state monads, or your favorite monad transformer stack.
+license:      BSD3
+license-file: LICENSE
+
+extra-source-files: 
+  README.md
+
+source-repository head
+  type: git
+  location: git://github.com/ninegua/monad-task.git
+
+Library
+  exposed-modules:
+    Control.Monad.Task
+    Control.Monad.Task.Class
+    Control.Monad.Trans.Task
+  build-depends: base < 6, mtl == 2.*, transformers < 0.4
+  extensions:
+  ghc-options: -Wall -fno-warn-unused-imports
