diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+0.2.1
+---------------------------------
+* Re-exported some `extensible` combinators.
+* Added `mapGondolas`.
+* Supported RWST.
+
+0.2
+---------------------------------
+* Switched to use extensible. Things will be faster and saner.
+* `elevate` is now more flexible.
+* `elevate` no longer has eager strategy, revealing potential ambiguousness.
+
 0.1.3
 ---------------------------------
 * Prevent the reckress type checking of GHC so that it works on older GHC and shows sane signature.
@@ -8,4 +20,4 @@
 
 0.1.1
 ---------------------------------
-* Added `elevate = id` pragma for efficiency.
+* Added `elevate = id` pragma for efficiency.
diff --git a/elevator.cabal b/elevator.cabal
--- a/elevator.cabal
+++ b/elevator.cabal
@@ -1,14 +1,15 @@
 name:                elevator
-version:             0.2
+version:             0.2.1
 synopsis:            Immediately lifts to a desired level
 description:         This package provides 'elevate' function which composes 'lift'-like transformations automatically.
 homepage:            https://github.com/fumieval/elevator
+bug-reports:         https://github.com/fumieval/elevator/issues
 license:             BSD3
 license-file:        LICENSE
 author:              Fumiaki Kinoshita
 maintainer:          Fumiaki Kinoshita <fumiexcel@gmail.com>
-copyright:           Copyright (C) 2014 Fumiaki Kinoshita
-category:            Data
+copyright:           Copyright (C) 2015 Fumiaki Kinoshita
+category:            Control
 build-type:          Simple
 extra-source-files:
     CHANGELOG.md
@@ -22,8 +23,7 @@
 
 library
   exposed-modules:     Control.Elevator
-  -- other-modules:
   other-extensions:    TypeOperators, FlexibleContexts, FlexibleInstances, ConstraintKinds, TypeFamilies, DataKinds
-  build-depends:       base == 4.*, transformers >= 0.3, extensible >= 0.2.6 && <0.3
+  build-depends:       base >= 4.7 && <5, transformers >= 0.3 && <0.5, extensible >= 0.2.6 && <0.3
   hs-source-dirs:      src
   default-language:    Haskell2010
diff --git a/src/Control/Elevator.hs b/src/Control/Elevator.hs
--- a/src/Control/Elevator.hs
+++ b/src/Control/Elevator.hs
@@ -1,176 +1,216 @@
-{-# LANGUAGE CPP, PolyKinds, TypeOperators, FlexibleContexts, Rank2Types, DefaultSignatures, FlexibleInstances, ConstraintKinds, TypeFamilies, DataKinds, UndecidableInstances #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Elevator
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
--- Automated effect elevator
---
------------------------------------------------------------------------------
-module Control.Elevator where
-import Control.Monad.Trans.State.Lazy as Lazy
-import Control.Monad.Trans.State.Strict as Strict
-import Control.Monad.Trans.Writer.Lazy as Lazy
-import Control.Monad.Trans.Writer.Strict as Strict
-import Control.Monad.Trans.Identity
-import Data.Functor.Identity
-import Data.Extensible
-import Data.Extensible.Internal
-import Data.Extensible.Union
-import Data.Extensible.League
-import Control.Applicative
-import Control.Monad
-import Control.Monad.Trans.Class
-import Control.Monad.Trans.Reader
-import Control.Monad.Trans.Maybe
-import Control.Monad.Trans.List
-import Data.Monoid
-import Control.Monad.ST
-import Data.Proxy
-import Unsafe.Coerce
-
-#ifndef MIN_VERSION_transformers
-#define MIN_VERSION_transformers(x,y,z) 1
-#endif
-
-#if MIN_VERSION_transformers(0,4,0)
-import Control.Monad.Trans.Except
-#else
-import Control.Monad.Trans.Error
-#endif
-
-rung :: (forall x. f x -> g x) -> Gondola g :* fs -> Gondola g :* (f ': fs)
-rung f = (<:) (Gondola f)
-infixr 0 `rung`
-
-newtype Gondola f g = Gondola { runGondola :: forall a. g a -> f a }
-
--- | A class of types which have bases.
-class Tower f where
-  type Floors (f :: * -> *) :: [* -> *]
-  type Floors f = '[Identity]
-
-  -- | The product of all ways to lift.
-  stairs :: Gondola f :* Floors f
-  default stairs :: Applicative f => Gondola f :* '[Identity]
-  stairs = pure . runIdentity `rung` Nil
-
--- | The parents and itself.
-type Floors1 f = f ': Floors f
-
--- | 'stairs' for 'Floors1'.
-stairs1 :: Tower f => Gondola f :* Floors1 f
-stairs1 = id `rung` stairs
-
--- | @f@ can be lifted to @g@
-type Elevate f g = (Tower g, f ∈ Floors1 g)
-
--- | Lift a thing, automatically.
-elevate :: Elevate f g => f a -> g a
-elevate = runGondola (hlookup membership stairs1)
-{-# RULES "elevate/id" [~2] elevate = id #-}
-{-# INLINE[2] elevate #-}
-
-instance Tower IO where
-  type Floors IO = '[ST RealWorld, Identity]
-  stairs = stToIO `rung` return . runIdentity `rung` Nil
-
-instance Tower Identity where
-  type Floors Identity = '[]
-  stairs = Nil
-
-instance Tower Maybe
-instance Tower (Either e)
-instance Tower ((->) r)
-instance Tower []
-instance Tower (ST s)
-
-instance Generate xs => Tower (Union xs) where
-  type Floors (Union xs) = xs
-  stairs = generate $ \pos -> Gondola $ Union . UnionAt pos . Flux id
-
-instance Forall Functor xs => Tower (League xs) where
-  type Floors (League xs) = xs
-  stairs = generateFor (Proxy :: Proxy Functor) $ \pos -> Gondola $ \f -> League $ UnionAt pos $ Fuse (<$>f)
-
-liftGondolas :: (Monad m, Tower m, MonadTrans t) => Gondola (t m) :* Floors1 m
-liftGondolas = hmap (\(Gondola f) -> Gondola $ lift . f) stairs1
-
-instance (Monad m, Tower m) => Tower (Lazy.StateT s m) where
-  type Floors (Lazy.StateT s m) = Floors1 m
-    ++ Map (Lazy.StateT s) (Floors m)
-    ++ Map (Strict.StateT s) (Floors1 m)
-  stairs = liftGondolas
-    *++* htrans (\(Gondola f) -> Gondola $ Lazy.mapStateT f) stairs
-    *++* htrans (\(Gondola f) -> Gondola $ Lazy.StateT . fmap f . Strict.runStateT) stairs1
-
-instance (Monad m, Tower m) => Tower (Strict.StateT s m) where
-  type Floors (Strict.StateT s m) = Floors1 m
-    ++ Map (Strict.StateT s) (Floors m)
-    ++ Map (Lazy.StateT s) (Floors1 m)
-  stairs = liftGondolas
-    *++* htrans (\(Gondola f) -> Gondola $ Strict.mapStateT f) stairs
-    *++* htrans (\(Gondola f) -> Gondola $ Strict.StateT . fmap f . Lazy.runStateT) stairs1
-
-instance (Monad m, Tower m) => Tower (ReaderT r m) where
-  type Floors (ReaderT r m) = Floors1 m
-    ++ (->) r
-    ': Map (ReaderT r) (Floors1 m)
-  stairs = liftGondolas
-    *++* reader
-    `rung` htrans (\(Gondola f) -> Gondola $ ReaderT . fmap f . runReaderT) stairs1
-
-instance (Monoid w, Monad m, Tower m) => Tower (Lazy.WriterT w m) where
-  type Floors (Lazy.WriterT w m) = Floors1 m
-    ++ Map (Lazy.WriterT w) (Floors m)
-    ++ Map (Strict.WriterT w) (Floors1 m)
-  stairs = liftGondolas
-    *++* htrans (\(Gondola f) -> Gondola $ Lazy.mapWriterT f) stairs
-    *++* htrans (\(Gondola f) -> Gondola $ Lazy.WriterT . f . Strict.runWriterT) stairs1
-
-instance (Monoid w, Monad m, Tower m) => Tower (Strict.WriterT w m) where
-  type Floors (Strict.WriterT w m) = Floors1 m
-    ++ Map (Strict.WriterT w) (Floors m)
-    ++ Map (Lazy.WriterT w) (Floors1 m)
-  stairs = liftGondolas
-    *++* htrans (\(Gondola f) -> Gondola $ Strict.mapWriterT f) stairs
-    *++* htrans (\(Gondola f) -> Gondola $ Strict.WriterT . f . Lazy.runWriterT) stairs1
-
-instance (Monad m, Tower m) => Tower (MaybeT m) where
-  type Floors (MaybeT m) = Floors1 m
-    ++ Maybe
-    ': Map MaybeT (Floors m)
-  stairs = liftGondolas
-    *++* MaybeT . return
-    `rung` htrans (\(Gondola f) -> Gondola $ mapMaybeT f) stairs
-
-instance (Monad m, Tower m) => Tower (ListT m) where
-  type Floors (ListT m) = Floors1 m
-    ++ []
-    ': Map ListT (Floors m)
-  stairs = liftGondolas
-    *++* ListT . return
-    `rung` htrans (\(Gondola f) -> Gondola $ mapListT f) stairs
-
-#if MIN_VERSION_transformers(0,4,0)
-instance (Monad m, Tower m) => Tower (ExceptT e m) where
-  type Floors (ExceptT e m) = Floors1 m
-    ++ Either e
-    ': Map (ExceptT e) (Floors m)
-  stairs = liftGondolas
-    *++* ExceptT . return
-    `rung` htrans (\(Gondola f) -> Gondola $ mapExceptT f) stairs
-#else
-instance (Error e, Monad m, Tower m) => Tower (ErrorT e m) where
-  type Floors (ErrorT e m) = Floors1 m
-    ++ Either e
-    ': Map (ErrorT e) (Floors m)
-  stairs = liftGondolas
-    *++* ErrorT . return
-    `rung` htrans (\(Gondola f) -> Gondola $ mapErrorT f) stairs
-#endif
+{-# LANGUAGE CPP, PolyKinds, TypeOperators, FlexibleContexts, Rank2Types, DefaultSignatures, FlexibleInstances, ConstraintKinds, TypeFamilies, DataKinds, UndecidableInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Elevator
+-- Copyright   :  (c) Fumiaki Kinoshita 2015
+-- License     :  BSD3
+--
+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Automated effect elevator
+--
+-----------------------------------------------------------------------------
+module Control.Elevator (Elevate
+  , elevate
+  -- * Construction kit
+  , Tower(..)
+  , Floors1
+  , stairs1
+  , Gondola(..)
+  , rung
+  , (:*)(Nil)
+  , (*++*)
+  , mapGondolas
+  , liftGondolas) where
+import Control.Monad.Trans.State.Lazy as Lazy
+import Control.Monad.Trans.State.Strict as Strict
+import Control.Monad.Trans.Writer.Lazy as Lazy
+import Control.Monad.Trans.Writer.Strict as Strict
+import Control.Monad.Trans.RWS.Lazy as LazyRWS
+import Control.Monad.Trans.RWS.Strict as StrictRWS
+import Control.Monad.Trans.Identity
+import Data.Functor.Identity
+import Data.Extensible
+import Data.Extensible.Internal
+import Data.Extensible.Union
+import Data.Extensible.League
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Reader as Reader
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.List
+import Data.Monoid
+import Control.Monad.ST
+import Data.Proxy
+import Unsafe.Coerce
+
+#ifndef MIN_VERSION_transformers
+#define MIN_VERSION_transformers(x,y,z) 1
+#endif
+
+#if MIN_VERSION_transformers(0,4,0)
+import Control.Monad.Trans.Except
+#else
+import Control.Monad.Trans.Error
+#endif
+
+-- | @f@ can be lifted to @g@
+type Elevate f g = (Tower g, f ∈ Floors1 g)
+
+-- | Lift a thing, automatically.
+elevate :: Elevate f g => f a -> g a
+elevate = runGondola (hlookup membership stairs1)
+{-# RULES "elevate/id" [~2] elevate = id #-}
+{-# INLINE[2] elevate #-}
+
+----------------------------------------------------------------------------
+
+-- | Transformation between effects
+newtype Gondola f g = Gondola { runGondola :: forall a. g a -> f a }
+
+-- | Add a new transformation.
+rung :: (forall x. f x -> g x) -> Gondola g :* fs -> Gondola g :* (f ': fs)
+rung f = (<:) (Gondola f)
+infixr 0 `rung`
+
+mapGondolas :: (forall x. m x -> n x) -> Gondola m :* xs -> Gondola n :* xs
+mapGondolas g = hmap (\(Gondola f) -> Gondola $ g . f)
+
+-- | A class of types which have bases.
+class Tower f where
+  type Floors (f :: * -> *) :: [* -> *]
+  type Floors f = '[Identity]
+
+  -- | The product of all ways to lift.
+  stairs :: Gondola f :* Floors f
+  default stairs :: Applicative f => Gondola f :* '[Identity]
+  stairs = pure . runIdentity `rung` Nil
+
+-- | The parents and itself.
+type Floors1 f = f ': Floors f
+
+-- | 'stairs' for 'Floors1'.
+stairs1 :: Tower f => Gondola f :* Floors1 f
+stairs1 = id `rung` stairs
+
+liftGondolas :: (Monad m, Tower m, MonadTrans t) => Gondola (t m) :* Floors1 m
+liftGondolas = mapGondolas lift stairs1
+
+instance Tower IO where
+  type Floors IO = '[ST RealWorld, Identity]
+  stairs = stToIO `rung` return . runIdentity `rung` Nil
+
+instance Tower Identity where
+  type Floors Identity = '[]
+  stairs = Nil
+
+instance Tower Maybe
+instance Tower (Either e)
+instance Tower ((->) r)
+instance Tower []
+instance Tower (ST s)
+
+instance Generate xs => Tower (Union xs) where
+  type Floors (Union xs) = xs
+  stairs = generate $ \pos -> Gondola $ Union . UnionAt pos . Flux id
+
+instance Forall Functor xs => Tower (League xs) where
+  type Floors (League xs) = xs
+  stairs = generateFor (Proxy :: Proxy Functor) $ \pos -> Gondola $ \f -> League $ UnionAt pos $ Fuse (<$>f)
+
+instance (Monad m, Tower m) => Tower (Lazy.StateT s m) where
+  type Floors (Lazy.StateT s m) = Floors1 m
+    ++ Map (Lazy.StateT s) (Floors m)
+    ++ Map (Strict.StateT s) (Floors1 m)
+  stairs = liftGondolas
+    *++* htrans (\(Gondola f) -> Gondola $ Lazy.mapStateT f) stairs
+    *++* htrans (\(Gondola f) -> Gondola $ Lazy.StateT . fmap f . Strict.runStateT) stairs1
+
+instance (Monad m, Tower m) => Tower (Strict.StateT s m) where
+  type Floors (Strict.StateT s m) = Floors1 m
+    ++ Map (Strict.StateT s) (Floors m)
+    ++ Map (Lazy.StateT s) (Floors1 m)
+  stairs = liftGondolas
+    *++* htrans (\(Gondola f) -> Gondola $ Strict.mapStateT f) stairs
+    *++* htrans (\(Gondola f) -> Gondola $ Strict.StateT . fmap f . Lazy.runStateT) stairs1
+
+instance (Monad m, Tower m) => Tower (ReaderT r m) where
+  type Floors (ReaderT r m) = Floors1 m
+    ++ (->) r
+    ': Map (ReaderT r) (Floors1 m)
+  stairs = liftGondolas
+    *++* Reader.reader
+    `rung` htrans (\(Gondola f) -> Gondola $ ReaderT . fmap f . runReaderT) stairs1
+
+instance (Monoid w, Monad m, Tower m) => Tower (Lazy.WriterT w m) where
+  type Floors (Lazy.WriterT w m) = Floors1 m
+    ++ Map (Lazy.WriterT w) (Floors m)
+    ++ Map (Strict.WriterT w) (Floors1 m)
+  stairs = liftGondolas
+    *++* htrans (\(Gondola f) -> Gondola $ Lazy.mapWriterT f) stairs
+    *++* htrans (\(Gondola f) -> Gondola $ Lazy.WriterT . f . Strict.runWriterT) stairs1
+
+instance (Monoid w, Monad m, Tower m) => Tower (Strict.WriterT w m) where
+  type Floors (Strict.WriterT w m) = Floors1 m
+    ++ Map (Strict.WriterT w) (Floors m)
+    ++ Map (Lazy.WriterT w) (Floors1 m)
+  stairs = liftGondolas
+    *++* htrans (\(Gondola f) -> Gondola $ Strict.mapWriterT f) stairs
+    *++* htrans (\(Gondola f) -> Gondola $ Strict.WriterT . f . Lazy.runWriterT) stairs1
+
+instance (Monad m, Tower m) => Tower (MaybeT m) where
+  type Floors (MaybeT m) = Floors1 m
+    ++ Maybe
+    ': Map MaybeT (Floors m)
+  stairs = liftGondolas
+    *++* MaybeT . return
+    `rung` htrans (\(Gondola f) -> Gondola $ mapMaybeT f) stairs
+
+instance (Monad m, Tower m) => Tower (ListT m) where
+  type Floors (ListT m) = Floors1 m
+    ++ []
+    ': Map ListT (Floors m)
+  stairs = liftGondolas
+    *++* ListT . return
+    `rung` htrans (\(Gondola f) -> Gondola $ mapListT f) stairs
+
+instance (Monad m, Tower m, Monoid w) => Tower (LazyRWS.RWST r w s m) where
+  type Floors (LazyRWS.RWST r w s m) = Floors1 m
+    ++ Map (ReaderT r) (Floors1 m)
+    ++ Map (Lazy.WriterT w) (Floors1 m)
+    ++ Map (Lazy.StateT s) (Floors1 m)
+  stairs = liftGondolas
+    *++* htrans (\(Gondola f) -> Gondola $ \g -> LazyRWS.RWST $ \r s -> f (runReaderT g r) >>= \a -> return (a, s, mempty)) stairs1
+    *++* htrans (\(Gondola f) -> Gondola $ \g -> LazyRWS.RWST $ \_ s -> f (Lazy.runWriterT g) >>= \(a, w) -> return (a, s, w)) stairs1
+    *++* htrans (\(Gondola f) -> Gondola $ \g -> LazyRWS.RWST $ \_ s -> f (Lazy.runStateT g s) >>= \(a, s') -> return (a, s', mempty)) stairs1
+
+instance (Monad m, Tower m, Monoid w) => Tower (StrictRWS.RWST r w s m) where
+  type Floors (StrictRWS.RWST r w s m) = Floors1 m
+    ++ Map (ReaderT r) (Floors1 m)
+    ++ Map (Strict.WriterT w) (Floors1 m)
+    ++ Map (Strict.StateT s) (Floors1 m)
+  stairs = liftGondolas
+    *++* htrans (\(Gondola f) -> Gondola $ \g -> StrictRWS.RWST $ \r s -> f (runReaderT g r) >>= \a -> return (a, s, mempty)) stairs1
+    *++* htrans (\(Gondola f) -> Gondola $ \g -> StrictRWS.RWST $ \_ s -> f (Strict.runWriterT g) >>= \(a, w) -> return (a, s, w)) stairs1
+    *++* htrans (\(Gondola f) -> Gondola $ \g -> StrictRWS.RWST $ \_ s -> f (Strict.runStateT g s) >>= \(a, s') -> return (a, s', mempty)) stairs1
+
+#if MIN_VERSION_transformers(0,4,0)
+instance (Monad m, Tower m) => Tower (ExceptT e m) where
+  type Floors (ExceptT e m) = Floors1 m
+    ++ Either e
+    ': Map (ExceptT e) (Floors m)
+  stairs = liftGondolas
+    *++* ExceptT . return
+    `rung` htrans (\(Gondola f) -> Gondola $ mapExceptT f) stairs
+#else
+instance (Error e, Monad m, Tower m) => Tower (ErrorT e m) where
+  type Floors (ErrorT e m) = Floors1 m
+    ++ Either e
+    ': Map (ErrorT e) (Floors m)
+  stairs = liftGondolas
+    *++* ErrorT . return
+    `rung` htrans (\(Gondola f) -> Gondola $ mapErrorT f) stairs
+#endif
