diff --git a/README.lhs b/README.lhs
--- a/README.lhs
+++ b/README.lhs
@@ -20,19 +20,15 @@
 
 main :: IO ()
 main = hspec $ do
-
   describe "shouldBe" $ do
-
     it "asserts equality" $ do
       "foo" `shouldBe` "foo"
 
   describe "shouldSatisfy" $ do
-
     it "asserts that a predicate holds" $ do
       "bar" `shouldSatisfy` (not . null)
 
   describe "shouldThrow" $ do
-
     it "asserts that an exception is thrown" $ do
       evaluate (1 `div` 0 :: Int) `shouldThrow` (== DivideByZero)
 ~~~
diff --git a/hspec-expectations.cabal b/hspec-expectations.cabal
--- a/hspec-expectations.cabal
+++ b/hspec-expectations.cabal
@@ -1,5 +1,5 @@
 name:             hspec-expectations
-version:          0.3.3
+version:          0.4.0
 synopsis:         Catchy combinators for HUnit
 description:      Catchy combinators for HUnit: <https://github.com/sol/hspec-expectations#readme>
 license:          MIT
@@ -22,10 +22,12 @@
   build-depends:
       base < 4.8
     , HUnit
+    , transformers
   hs-source-dirs:
       src
   exposed-modules:
       Test.Hspec.Expectations
+    , Test.Hspec.Expectations.Lifted
     , Test.Hspec.Expectations.Contrib
 
 test-suite spec
@@ -41,6 +43,7 @@
   build-depends:
       base
     , HUnit
+    , transformers
     , silently
     , hspec       >= 1.3
 
diff --git a/src/Test/Hspec/Expectations.hs b/src/Test/Hspec/Expectations.hs
--- a/src/Test/Hspec/Expectations.hs
+++ b/src/Test/Hspec/Expectations.hs
@@ -36,7 +36,6 @@
 , errorCall
 ) where
 
-import           Prelude
 import           Test.HUnit (Assertion, (@?=), assertBool, assertFailure)
 import           Control.Exception
 import           Data.Typeable
@@ -48,7 +47,7 @@
 expectationFailure :: String -> Expectation
 expectationFailure = assertFailure
 
-infix 1 `shouldBe`, `shouldSatisfy`, `shouldReturn`, `shouldThrow`
+infix 1 `shouldBe`, `shouldSatisfy`, `shouldContain`, `shouldReturn`, `shouldThrow`
 
 -- |
 -- @actual \`shouldBe\` expected@ sets the expectation that @actual@ is equal
diff --git a/src/Test/Hspec/Expectations/Lifted.hs b/src/Test/Hspec/Expectations/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/Hspec/Expectations/Lifted.hs
@@ -0,0 +1,81 @@
+-- |
+-- Introductory documentation: <https://github.com/sol/hspec-expectations#readme>
+module Test.Hspec.Expectations.Lifted (
+
+-- * Setting expectations
+  Expectation
+, expectationFailure
+, shouldBe
+, shouldSatisfy
+, shouldContain
+, shouldReturn
+
+-- * Expecting exceptions
+, shouldThrow
+
+-- ** Selecting exceptions
+, Selector
+
+-- ** Predefined type-based selectors
+-- |
+-- There are predefined selectors for some standard exceptions.  Each selector
+-- is just @const True@ with an appropriate type.
+, anyException
+, anyErrorCall
+, anyIOException
+, anyArithException
+
+-- ** Combinators for defining value-based selectors
+-- |
+-- Some exceptions (most prominently `ErrorCall`) have no `Eq` instance.
+-- Selecting a specific value would require pattern matching.
+--
+-- For such exceptions, combinators that construct selectors are provided.
+-- Each combinator corresponds to a constructor; it takes the same arguments,
+-- and has the same name (but starting with a lower-case letter).
+, errorCall
+) where
+
+import           Control.Exception
+import           Control.Monad.IO.Class
+import           Test.Hspec.Expectations hiding (expectationFailure, shouldBe, shouldSatisfy, shouldContain, shouldReturn, shouldThrow)
+import qualified Test.Hspec.Expectations as E
+
+infix 1 `shouldBe`, `shouldSatisfy`, `shouldContain`, `shouldReturn`, `shouldThrow`
+
+liftIO2 :: MonadIO m => (a -> b -> IO r) -> a -> b -> m r
+liftIO2 action a = liftIO . action a
+
+-- | This is just an alias for HUnit's `assertFailure`.
+expectationFailure :: MonadIO m => String -> m ()
+expectationFailure = liftIO . E.expectationFailure
+
+-- |
+-- @actual \`shouldBe\` expected@ sets the expectation that @actual@ is equal
+-- to @expected@ (this is just an alias for `@?=`).
+shouldBe :: (Show a, Eq a, MonadIO m) => a -> a -> m ()
+shouldBe = liftIO2 E.shouldBe
+
+-- |
+-- @v \`shouldSatisfy\` p@ sets the expectation that @p v@ is @True@.
+shouldSatisfy :: (Show a, MonadIO m) => a -> (a -> Bool) -> m ()
+shouldSatisfy = liftIO2 E.shouldSatisfy
+
+-- |
+-- @list \`shouldContain\` sublist@ sets the expectation that @sublist@ is contained,
+-- wholly and intact, anywhere in the second.
+shouldContain :: (Show a, Eq a, MonadIO m) => [a] -> [a] -> m ()
+shouldContain = liftIO2 E.shouldContain
+
+-- |
+-- @action \`shouldReturn\` expected@ sets the expectation that @action@
+-- returns @expected@.
+shouldReturn :: (Show a, Eq a, MonadIO m) => IO a -> a -> m ()
+shouldReturn = liftIO2 E.shouldReturn
+
+-- |
+-- @action \`shouldThrow\` selector@ sets the expectation that @action@ throws
+-- an exception.  The precise nature of the expected exception is described
+-- with a 'Selector'.
+shouldThrow :: (Exception e, MonadIO m) => IO a -> Selector e -> m ()
+shouldThrow = liftIO2 E.shouldThrow
