diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,3 @@
+## v0.2.0 - 2014-05-01
+
+* Generalize `Concurrently` (#4)
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+lifted-async
+==========
+[![Build Status](https://secure.travis-ci.org/maoe/lifted-async.png)](http://travis-ci.org/maoe/lifted-async)
+[![Coverage Status](https://coveralls.io/repos/maoe/lifted-async/badge.png)](https://coveralls.io/r/maoe/lifted-async)
+
+This package provides IO operations from [async](http://hackage.haskell.org/package/async) package lifted to any instance of `MonadBase` or `MonadBaseControl` from [monad-control](http://hackage.haskell.org/package/monad-control) package.
+
+You can install this library using cabal:
+
+```
+cabal install lifted-async
+```
+
+Contact information
+==========
+
+This library is written and maintained by Mitsutoshi Aoe <maoe@foldr.in>.
+[Pull requests](https://github.com/maoe/lifted-async/pulls) and [bug reports](https://github.com/maoe/lifted-async/issues) are welcome. A chat room is available on [Gitter](https://gitter.im/maoe/lifted-async).
diff --git a/lifted-async.cabal b/lifted-async.cabal
--- a/lifted-async.cabal
+++ b/lifted-async.cabal
@@ -1,5 +1,5 @@
 name:                lifted-async
-version:             0.1.2
+version:             0.2.0
 synopsis:            Run lifted IO operations asynchronously and wait for their results
 homepage:            https://github.com/maoe/lifted-async
 bug-reports:         https://github.com/maoe/lifted-async/issues
@@ -12,6 +12,10 @@
 build-type:          Simple
 cabal-version:       >= 1.8
 
+extra-source-files:
+  README.md
+  CHANGELOG.md
+
 description:
   This package provides IO operations from @async@ package lifted to any
   instance of 'MonadBase' or 'MonadBaseControl'.
@@ -91,5 +95,5 @@
 
 source-repository this
   type: git
-  tag: v0.1.2
+  tag: v0.2.0
   location: https://github.com/maoe/lifted-async.git
diff --git a/src/Control/Concurrent/Async/Lifted.hs b/src/Control/Concurrent/Async/Lifted.hs
--- a/src/Control/Concurrent/Async/Lifted.hs
+++ b/src/Control/Concurrent/Async/Lifted.hs
@@ -1,5 +1,7 @@
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE TypeFamilies #-}
 
 {- |
 Module      : Control.Concurrent.Async.Lifted
@@ -40,10 +42,12 @@
 
     -- * Convenient utilities
   , race, race_, concurrently, mapConcurrently
-  , A.Concurrently (..)
+  , Concurrently(..)
   ) where
 
-import Control.Monad ((>=>), liftM, void)
+import Control.Applicative
+import Control.Concurrent (threadDelay)
+import Control.Monad ((>=>), forever, liftM, void)
 import Data.Traversable (Traversable(..))
 import GHC.IO (unsafeUnmask)
 import Prelude hiding (mapM)
@@ -313,10 +317,42 @@
   => (a -> m b)
   -> t a
   -> m (t b)
-mapConcurrently f t =
-  liftBaseWith (\runInIO ->
-    A.runConcurrently $ traverse (A.Concurrently . runInIO . f) t) >>=
-  mapM restoreM
+mapConcurrently f = runConcurrently . traverse (Concurrently . f)
+
+-- | Generalized version of 'A.Concurrently'.
+--
+-- A value of type @Concurrently b m a@ is an IO-based operation that can be
+-- composed with other 'Concurrently' values, using the 'Applicative' and
+-- 'Alternative' instances.
+--
+-- Calling 'runConcurrently' on a value of type @Concurrently b m a@ will
+-- execute the IO-based lifted operations it contains concurrently, before
+-- delivering the result of type 'a'.
+--
+-- For example
+-- > (page1, page2, page3) <- runConcurrently $ (,,)
+-- >   <$> Concurrently (getURL "url1")
+-- >   <*> Concurrently (getURL "url2")
+-- >   <*> Concurrently (getURL "url3")
+newtype Concurrently (b :: * -> *) m a = Concurrently { runConcurrently :: m a }
+
+-- NOTE: The phantom type variable @b :: * -> *@ in 'Concurrently' is needed to
+-- avoid @UndecidableInstances@ in the following instance declarations.
+-- See https://github.com/maoe/lifted-async/issues/4 for alternative
+-- implementaions.
+
+instance (b ~ IO, Functor m) => Functor (Concurrently b m) where
+  fmap f (Concurrently a) = Concurrently $ f <$> a
+
+instance (b ~ IO, MonadBaseControl b m) => Applicative (Concurrently b m) where
+  pure = Concurrently . pure
+  Concurrently fs <*> Concurrently as =
+    Concurrently $ uncurry ($) <$> concurrently fs as
+
+instance (b ~ IO, MonadBaseControl b m) => Alternative (Concurrently b m) where
+  empty = Concurrently . liftBaseWith . const $ forever (threadDelay maxBound)
+  Concurrently as <|> Concurrently bs =
+    Concurrently $ either id id <$> race as bs
 
 sequenceEither :: MonadBaseControl IO m => Either e (StM m a) -> m (Either e a)
 sequenceEither = either (return . Left) (liftM Right . restoreM)
