diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2013, Dan Burton
+
+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 Dan Burton 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/MHask.cabal b/MHask.cabal
new file mode 100644
--- /dev/null
+++ b/MHask.cabal
@@ -0,0 +1,36 @@
+-- Initial MHask.cabal generated by cabal init.  For further documentation,
+--  see http://haskell.org/cabal/users-guide/
+
+name:                MHask
+version:             0.1.0.0
+synopsis:            The category of monads
+category:            Control
+description:         
+  MHask is the category where
+  .
+  * The objects are Haskell types of kind (* -> *) that have an instance of Monad
+  * An arrow from object m to object n is a Haskell function of the form (forall x. m x -> n x)
+  * Arrow composition is merely a specialization of Haskell function composition
+  * The identity arrow for the object m is the id function in Haskell, specialized to (forall x. m x -> m x)
+  .
+  Functor should actually be called Endofunctor, because if m is an object in MHask,
+  then an instance t of Functor can transform object m into object (t m).
+  You will see *a lot* of constraints in the type classes defined herein.
+  Though daunting at first, you will soon realize that they are *all* Prelude.Monad constraints,
+  and their interpretation is simply a guarantee that
+  "the objects of MHask are types of kind (* -> *) that have an instance of Monad."
+
+homepage:            https://github.com/DanBurton/MHask#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Dan Burton
+maintainer:          danburton.email@gmail.com
+-- copyright:           
+-- category:            
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules:     MHask, MHask.Comonad, MHask.Monad, MHask.Copointed, MHask.Pointed, MHask.Util, MHask.Functor, MHask.Indexed.Comonad, MHask.Indexed.Monad, MHask.Indexed.Copointed, MHask.Indexed.Pointed, MHask.Indexed.Functor
+  -- other-modules:       
+  build-depends:       base == 4.6.*, transformers >= 0.3
diff --git a/MHask.hs b/MHask.hs
new file mode 100644
--- /dev/null
+++ b/MHask.hs
@@ -0,0 +1,16 @@
+
+module MHask (module MHask) where
+
+import MHask.Util as MHask
+
+import qualified MHask.Functor as MHask
+import qualified MHask.Pointed as MHask
+import qualified MHask.Monad   as MHask
+import qualified MHask.Copointed as MHask
+import qualified MHask.Comonad as MHask
+
+import qualified MHask.Indexed.Functor as MHask
+import qualified MHask.Indexed.Pointed as MHask
+import qualified MHask.Indexed.Monad   as MHask
+import qualified MHask.Indexed.Copointed as MHask
+import qualified MHask.Indexed.Comonad as MHask
diff --git a/MHask/Comonad.hs b/MHask/Comonad.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Comonad.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE DefaultSignatures #-}
+
+-- Compare to comonad.Control.Comonad (Comonad)
+module MHask.Comonad where
+
+import MHask.Util
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+import qualified MHask.Functor as MHask
+import qualified MHask.Copointed as MHask
+
+
+class (MHask.Copointed t) => Comonad t where
+  extend :: (Monad m, Monad n, Monad (t m), Monad (t n))
+    => (t m ~> n) -> (t m ~> t n)
+  default extend :: (Monad m, Monad n, Monad (t m), Monad (t n),
+                     Monad (t (t m)))
+    => (t m ~> n) -> (t m ~> t n)
+  extend f = duplicate ~> MHask.fmap f
+
+  duplicate :: (Monad m, Monad (t m), Monad (t (t m)))
+    => t m ~> t (t m)
+  duplicate = extend id
diff --git a/MHask/Copointed.hs b/MHask/Copointed.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Copointed.hs
@@ -0,0 +1,32 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+
+
+-- Compare to todo.Copointed
+module MHask.Copointed where
+
+import MHask.Util
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+import Data.Monoid
+import Control.Monad (liftM)
+
+import qualified MHask.Functor as MHask
+
+
+class (MHask.Functor t) => Copointed t where
+  extract :: (Monad m, Monad (t m))
+    => t m ~> m
+
+
+instance Copointed (WriterT w) where
+  extract = liftM fst . runWriterT
+
+instance (Monoid s) => Copointed (StateT s) where
+  extract = flip evalStateT mempty
+
+instance (Monoid r) => Copointed (ReaderT r) where
+  extract = flip runReaderT mempty
diff --git a/MHask/Functor.hs b/MHask/Functor.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Functor.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+
+-- Compare to base.Prelude.Functor (Functor)
+module MHask.Functor where
+
+import Prelude hiding (Functor, fmap)
+import MHask.Util
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+
+class Functor t where
+  fmap :: (Monad m, Monad n, Monad (t m), Monad (t n))
+    => (m ~> n) -> (t m ~> t n)
+
+
+instance Functor (StateT s) where
+  fmap f m = StateT $ \s -> f (runStateT m s)
+
+instance Functor (ReaderT r) where
+  fmap f m = ReaderT $ \r -> f (runReaderT m r)
+
+instance Functor (WriterT w) where
+  fmap f m = WriterT $ f (runWriterT m)
+
diff --git a/MHask/Indexed/Comonad.hs b/MHask/Indexed/Comonad.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Indexed/Comonad.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE DefaultSignatures #-}
+
+-- Compare to indexed.Control.Comonad.Indexed (IxComonad)
+module MHask.Indexed.Comonad where
+
+import MHask.Util
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+import qualified MHask.Indexed.Functor as MHask
+import qualified MHask.Indexed.Copointed as MHask
+
+
+class (MHask.IxCopointed t) => IxComonad t where
+  iextend :: (Monad m, Monad n,
+             Monad (t i j m), Monad (t j k n), Monad (t i k m))
+    => (t j k m ~> n) -> (t i k m ~> t i j n)
+  default iextend :: (Monad m, Monad n,
+             Monad (t i j m), Monad (t j k n), Monad (t i k m),
+             Monad (t i j (t j k m)), Monad (t j k m), Monad (t i j n))
+    => (t j k m ~> n) -> (t i k m ~> t i j n)
+  iextend f = iduplicate ~> MHask.imap f
+
+  iduplicate :: (Monad m, Monad (t i k m), Monad (t i j (t j k m)))
+    => t i k m ~> t i j (t j k m)
+
+  default iduplicate :: (Monad m, Monad (t i k m), Monad (t i j (t j k m)),
+                          (Monad (t j k (t j k m))), (Monad (t i j m)),  (Monad (t j k m)))
+    => t i k m ~> t i j (t j k m)
+  iduplicate = iextend id
diff --git a/MHask/Indexed/Copointed.hs b/MHask/Indexed/Copointed.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Indexed/Copointed.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE DefaultSignatures #-}
+
+-- Compare to indexed.Data.Functor.Indexed (IxCopointed)
+module MHask.Indexed.Copointed where
+
+import MHask.Util
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+import qualified MHask.Copointed as MHask
+import qualified MHask.Indexed.Functor as MHask
+
+class (MHask.IxFunctor t) => IxCopointed t where
+  iextract :: (Monad m, Monad (t i i m))
+    => t i i m ~> m
+  default iextract :: (Monad m, Monad (t i i m), MHask.Copointed (t i i))
+    => t i i m ~> m
+  iextract = MHask.extract
diff --git a/MHask/Indexed/Functor.hs b/MHask/Indexed/Functor.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Indexed/Functor.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE DefaultSignatures #-}
+
+-- Compare to indexed.Data.Functor.Indexed (IxFunctor)
+module MHask.Indexed.Functor where
+
+import MHask.Util
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+import qualified MHask.Functor as MHask
+
+class IxFunctor t where
+  imap :: (Monad m, Monad n, Monad (t i j m), Monad (t i j n))
+    => (m ~> n) -> (t i j m ~> t i j n)
+  default imap :: (Monad m, Monad n, Monad (t i j m), Monad (t i j n),
+                     MHask.Functor (t i j))
+    => (m ~> n) -> (t i j m ~> t i j n)
+  imap = MHask.fmap
diff --git a/MHask/Indexed/Monad.hs b/MHask/Indexed/Monad.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Indexed/Monad.hs
@@ -0,0 +1,32 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE DefaultSignatures #-}
+
+-- Compare to indexed.Control.Monad.Indexed (IxMonad)
+module MHask.Indexed.Monad where
+
+import MHask.Util
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+import qualified MHask.Monad as MHask
+import qualified MHask.Indexed.Pointed as MHask
+import qualified MHask.Indexed.Functor as MHask
+
+class (MHask.IxPointed t) => IxMonad t where
+  ijoin :: (Monad m, Monad (t i j (t j k m)), Monad (t i k m))
+    => t i j (t j k m) ~> t i k m
+  default ijoin :: (Monad m, Monad (t i j (t j k m)), Monad (t i k m),
+                     Monad (t j k m))
+    => t i j (t j k m) ~> t i k m
+  ijoin = ibind id
+
+
+  ibind :: (Monad m, Monad (t i j m), Monad n, Monad (t j k n))
+    => (m ~> t j k n) -> (t i j m ~> t i k n)
+  default ibind :: (Monad m, Monad (t i j m), Monad n, Monad (t j k n),
+             Monad (t i k n), Monad (t i j (t j k n)))
+    => (m ~> t j k n) -> (t i j m ~> t i k n)
+  ibind f = MHask.imap f ~> ijoin
diff --git a/MHask/Indexed/Pointed.hs b/MHask/Indexed/Pointed.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Indexed/Pointed.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE DefaultSignatures #-}
+
+-- Compare to indexed.Data.Functor.Indexed (IxPointed)
+module MHask.Indexed.Pointed where
+
+import MHask.Util
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+import qualified MHask.Pointed as MHask
+import qualified MHask.Indexed.Functor as MHask
+
+class (MHask.IxFunctor t) => IxPointed t where
+  ireturn :: (Monad m, Monad (t i i m))
+    => m ~> t i i m
+  default ireturn :: (Monad m, Monad (t i i m), MHask.Pointed (t i i))
+    => m ~> t i i m
+  ireturn = MHask.return
diff --git a/MHask/Monad.hs b/MHask/Monad.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Monad.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE DefaultSignatures #-}
+
+-- Compare to base.Prelude.Monad
+module MHask.Monad where
+
+import Prelude hiding (Monad, join)
+import qualified Prelude as P
+import MHask.Util
+
+import qualified MHask.Functor as MHask
+import qualified MHask.Pointed as MHask
+
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+
+
+class (MHask.Pointed t) => Monad t where
+  join :: (P.Monad m, P.Monad (t m), P.Monad (t (t m)))
+    => t (t m) ~> t m
+  join = bind id
+
+  bind :: (P.Monad m, P.Monad (t m), P.Monad n, P.Monad (t n))
+    => (m ~> t n) -> (t m ~> t n)
+  default bind :: (P.Monad m, P.Monad (t m), P.Monad n, P.Monad (t n),
+                   P.Monad (t (t n)))
+    => (m ~> t n) -> (t m ~> t n)
+  bind f = MHask.fmap f ~> join
diff --git a/MHask/Pointed.hs b/MHask/Pointed.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Pointed.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+
+-- no relevant comparison
+module MHask.Pointed where
+
+import Prelude hiding (return)
+import MHask.Util
+
+import Data.Monoid
+import Control.Monad (liftM)
+import Control.Monad.Trans.State
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Writer
+import Control.Monad.Trans.Class
+
+import qualified MHask.Functor as MHask
+
+class (MHask.Functor t) => Pointed t where
+  return :: (Monad m, Monad (t m))
+    => (m ~> t m)
+
+
+-- This is basically MonadTrans
+-- lift = MHask.return
+
+instance Pointed (StateT s) where
+  return mx = StateT $ \s -> liftM (\x -> (x, s)) mx
+
+instance Pointed (ReaderT r) where
+  return mx = ReaderT $ \_ -> mx
+
+instance Monoid w => Pointed (WriterT w) where
+  return mx = WriterT $ liftM (\x -> (x, mempty)) mx
diff --git a/MHask/Util.hs b/MHask/Util.hs
new file mode 100644
--- /dev/null
+++ b/MHask/Util.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+
+module MHask.Util where
+
+type m ~> n = forall x. m x -> n x
+
+(~>) :: (Monad a, Monad b, Monad c) => (a ~> b) -> (b ~> c) -> (a ~> c)
+f1 ~> f2 = f2 . f1
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
