diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,4 @@
+# CHANGELOG
+
+## 0.0.1
+First working version
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, Aleksey Uimanov
+
+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 Aleksey Uimanov 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,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/hreader.cabal b/hreader.cabal
new file mode 100644
--- /dev/null
+++ b/hreader.cabal
@@ -0,0 +1,44 @@
+name:                hreader
+version:             0.0.1
+synopsis:            Generalization of MonadReader and ReaderT
+license:             BSD3
+license-file:        LICENSE
+author:              Aleksey Uimanov
+maintainer:          s9gf4ult@gmail.com
+category:            Control
+build-type:          Simple
+cabal-version:       >=1.10
+extra-source-files:  CHANGELOG.md
+homepage: https://bitbucket.org/s9gf4ult/hreader
+source-repository head
+  type: git
+  location: git@bitbucket.org:s9gf4ult/hreader.git
+
+
+library
+  default-language:    Haskell2010
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+
+  default-extensions: CPP
+                    , DataKinds
+                    , DeriveDataTypeable
+                    , DeriveGeneric
+                    , FlexibleContexts
+                    , FlexibleInstances
+                    , GeneralizedNewtypeDeriving
+                    , MultiParamTypeClasses
+                    , StandaloneDeriving
+                    , TypeFamilies
+                    , UndecidableInstances
+
+  build-depends:       base  >= 4.7   && < 5
+                     , exceptions
+                     , hset  >= 0.1.0 && < 1.0.0
+                     , mmorph
+                     , monad-control
+                     , mtl
+                     , transformers-base
+
+  exposed-modules:     Control.Monad.HReader
+                     , Control.Monad.HReader.Class
diff --git a/src/Control/Monad/HReader.hs b/src/Control/Monad/HReader.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/HReader.hs
@@ -0,0 +1,80 @@
+module Control.Monad.HReader where
+
+import Control.Monad.Base
+import Control.Monad.Catch
+import Control.Monad.Cont
+import Control.Monad.HReader.Class
+import Control.Monad.Morph
+import Control.Monad.Reader
+import Control.Monad.State
+import Control.Monad.Trans.Control
+import Control.Monad.Writer
+import Data.HSet
+import Data.Typeable
+import GHC.Generics
+
+#if MIN_VERSION_mtl(2, 2, 1)
+import Control.Monad.Except
+#else
+import Control.Monad.Error
+#endif
+
+newtype HReaderT els m a = HReaderT
+    { unHReaderT :: ReaderT (HSet els) m a
+    } deriving ( Functor, Applicative, Monad, MonadIO
+               , MonadError e, MonadCont, MonadWriter w
+               , MonadState s, MonadBase b
+               , MonadThrow, MonadCatch
+               , Typeable, Generic  )
+
+runUnversalT :: HSet els -> HReaderT els m a -> m a
+runUnversalT h (HReaderT r) = runReaderT r h
+
+instance MonadTrans (HReaderT els) where
+  lift = HReaderT . lift
+
+instance (MonadReader r m) => MonadReader r (HReaderT els m) where
+  ask = lift ask
+  local f ma = HReaderT $ do
+    h <- ask
+    lift $ do
+      local f $ runUnversalT h ma
+
+instance (Monad m) => MonadHReader (HReaderT els m) where
+  type HSetElements (HReaderT els m) = els
+  askHSet = HReaderT ask
+
+deriving instance MFunctor (HReaderT els)
+deriving instance MMonad (HReaderT els)
+
+#if MIN_VERSION_monad_control(1, 0, 0)
+instance MonadTransControl (HReaderT els) where
+  type StT (HReaderT els) a = StT (ReaderT (HSet els)) a
+  liftWith action = HReaderT $ do
+    liftWith $ \runTrans -> action (runTrans . unHReaderT)
+  restoreT = HReaderT . restoreT
+
+instance (MonadBaseControl b m) => MonadBaseControl b (HReaderT els m) where
+  type StM (HReaderT els m) a = StM (ReaderT (HSet els) m) a
+  liftBaseWith action = HReaderT $ do
+    liftBaseWith $ \runInBase -> action (runInBase . unHReaderT)
+  restoreM = HReaderT . restoreM
+#else
+instance MonadTransControl (HReaderT els) where
+  newtype StT (HReaderT els) a
+    = HRtTT
+      { unHRtTT :: StT (ReaderT (HSet els)) a
+      }
+  liftWith action = HReaderT $ do
+    liftWith $ \runTrans -> do
+      action ((HRtTT `liftM`) . runTrans . unHReaderT)
+  restoreT st = HReaderT $ restoreT $ unHRtTT `liftM` st
+
+instance (MonadBaseControl b m) => MonadBaseControl b (HReaderT els m) where
+  newtype StM (HReaderT els m) a
+    = HRtMT (StM (ReaderT (HSet els) m) a)
+  liftBaseWith action = HReaderT $ do
+    liftBaseWith $ \runInBase -> do
+      action ((HRtMT `liftM`) . runInBase . unHReaderT)
+  restoreM (HRtMT st) = HReaderT $ restoreM st
+#endif
diff --git a/src/Control/Monad/HReader/Class.hs b/src/Control/Monad/HReader/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/HReader/Class.hs
@@ -0,0 +1,69 @@
+module Control.Monad.HReader.Class where
+
+import Control.Monad.Cont
+import Control.Monad.List
+import Control.Monad.Reader
+import Data.HSet
+
+#if MIN_VERSION_mtl(2, 2, 1)
+import Control.Monad.Except
+#endif
+
+import qualified Control.Monad.RWS.Lazy   as RWSL
+import qualified Control.Monad.RWS.Strict as RWSS
+import qualified Control.Monad.State.Lazy   as SL
+import qualified Control.Monad.State.Strict as SS
+import qualified Control.Monad.Writer.Lazy   as WL
+import qualified Control.Monad.Writer.Strict as WS
+
+
+#if MIN_VERSION_base(4, 8, 0)
+class (Monad m) => MonadHReader m where
+#else
+class (Monad m, Applicative m) => MonadHReader m where
+#endif
+  type HSetElements m :: [*]
+  askHSet :: m (HSet (HSetElements m))
+
+-- | Ask arbitrary element of hset inside HReader
+haskM :: (MonadHReader m, Contains (HSetElements m) e)
+      => m e
+haskM = hget <$> askHSet
+
+-- | Ask arbitrary labeled element of hset in HReader
+haskLabeledM :: (MonadHReader m, Contains (HSetElements m) (Labeled label e))
+             => proxy label -> m e
+haskLabeledM p = hgetLabeled p <$> askHSet
+
+#define MHR(MONAD)                                        \
+instance (MonadHReader m) => MonadHReader (MONAD) where { \
+  type HSetElements (MONAD) = HSetElements m ;            \
+  askHSet = lift askHSet ;                                \
+  }
+
+MHR(ReaderT r m)
+MHR(ContT r m)
+MHR(ListT m)
+
+#if MIN_VERSION_mtl(2, 2, 1)
+MHR(ExceptT e m)
+#endif
+
+MHR(SL.StateT s m)
+MHR(SS.StateT s m)
+
+instance (MonadHReader m, Monoid w) => MonadHReader (WL.WriterT w m) where
+  type HSetElements (WL.WriterT w m) = HSetElements m
+  askHSet = lift askHSet
+
+instance (MonadHReader m, Monoid w) => MonadHReader (WS.WriterT w m) where
+  type HSetElements (WS.WriterT w m) = HSetElements m
+  askHSet = lift askHSet
+
+instance (MonadHReader m, Monoid w) => MonadHReader (RWSL.RWST r w s m) where
+  type HSetElements (RWSL.RWST r w s m) = HSetElements m
+  askHSet = lift askHSet
+
+instance (MonadHReader m, Monoid w) => MonadHReader (RWSS.RWST r w s m) where
+  type HSetElements (RWSS.RWST r w s m) = HSetElements m
+  askHSet = lift askHSet
