diff --git a/Specs.hs b/Specs.hs
deleted file mode 100644
--- a/Specs.hs
+++ /dev/null
@@ -1,158 +0,0 @@
-{-# OPTIONS_GHC -fno-warn-deprecations #-}
-module Main (main) where
-
-import           Test.Hspec.ShouldBe (Specs, describe, it, hspecX)
-
-import qualified Test.Hspec as H
-import           Test.Hspec hiding (Specs, describe, it, hspecX)
-import           Test.Hspec.Runner (hHspecWithFormat)
-import           Test.Hspec.Internal (SpecTree(..), Spec(..), Result(..), quantify)
-import           Test.Hspec.Formatters
-import           Test.Hspec.QuickCheck
-import           Test.Hspec.HUnit ()
-import           Test.HUnit
-import           System.IO
-import           System.IO.Silently
-import           Data.List (isPrefixOf)
-import qualified Test.HUnit as HUnit
-
-main :: IO ()
-main = specs >>= hspecX
-
-specs :: IO Specs
-specs = do
-  let testSpecs = [H.describe "Example" [
-          H.it "success" (Success),
-          H.it "fail 1" (Fail "fail message"),
-          H.it "pending" (pending "pending message"),
-          H.it "fail 2" (HUnit.assertEqual "assertEqual test" 1 (2::Int)),
-          H.it "exceptions" (undefined :: Bool),
-          H.it "quickcheck" (property $ \ i -> i == (i+1::Integer))]
-          ]
-
-  (reportContents, exampleSpecs)     <- capture $ hHspecWithFormat specdoc         False stdout testSpecs
-  (silentReportContents, _)          <- capture $ hHspecWithFormat silent          False stdout testSpecs
-  (progressReportContents, _)        <- capture $ hHspecWithFormat progress        False stdout testSpecs
-  (failed_examplesReportContents, _) <- capture $ hHspecWithFormat failed_examples False stdout testSpecs
-
-  let report = lines reportContents
-
-  return $ do
-    describe "the \"describe\" function" $ do
-        it "takes a description of what the behavior is for" $
-            case exampleSpecs of
-              [SpecGroup "Example" _] -> True
-              _ -> False
-
-        it "groups behaviors for what's being described" $
-            case exampleSpecs of
-              [SpecGroup _ xs] -> length xs == 6
-              _ -> False
-
-        describe "a nested description" $ do
-            it "has it's own specs"
-                (True)
-
-    describe "the \"it\" function" $ do
-        it "takes a description of a desired behavior" $
-            case unSpec $ H.it "whatever" Success of
-              SpecExample requirement _ -> requirement == "whatever"
-              _ -> False
-
-        it "takes an example of that behavior" $ do
-            case unSpec $ H.it "whatever" Success of
-              SpecExample _ example -> do
-                r <- example
-                r @?= Success
-              SpecGroup _ _ -> assertFailure "unexpected SpecGroup"
-
-        it "can use a Bool, HUnit Test, QuickCheck property, or \"pending\" as an example"
-            (True)
-
-        it "will treat exceptions as failures"
-            (any (==" - exceptions FAILED [3]") report)
-
-    describe "the \"hspec\" function" $ do
-        it "displays a header for each thing being described"
-            (any (=="Example") report)
-
-        it "displays one row for each behavior"
-            (HUnit.assertEqual "" 29 (length report))
-
-        it "displays a row for each successfull, failed, or pending example"
-            (any (==" - success") report && any (==" - fail 1 FAILED [1]") report)
-
-        it "displays a detailed list of failed examples"
-            (any (=="1) Example fail 1 FAILED") report)
-
-        it "displays a '#' with an additional message for pending examples"
-            (any (=="     # PENDING: pending message") report )
-
-        it "summarizes the time it takes to finish"
-            (any ("Finished in " `isPrefixOf`) report)
-
-        it "summarizes the number of examples and failures"
-            (any (=="6 examples, 4 failures") report)
-
-        it "outputs failed examples in red, pending in yellow, and successful in green"
-            (True)
-
-    describe "Bool as an example" $ do
-        it "is just an expression that evaluates to a Bool"
-            (True)
-
-    describe "HUnit TestCase as an example" $ do
-        it "is specified with the HUnit \"TestCase\" data constructor"
-            (HUnit.TestCase $ HUnit.assertBool "example" True)
-
-        it "is the assumed example for IO() actions"
-            (HUnit.assertBool "example" True)
-
-        it "will show the failed assertion text if available (e.g. assertBool)" $ do
-          (innerReport, _) <- capture $ hspec $ [H.describe "" [ H.it "" (HUnit.assertBool "trivial" False)]]
-          HUnit.assertBool "should find assertion text" $ any (=="trivial") (lines innerReport)
-
-        it "will show the failed assertion expected and actual values if available (e.g. assertEqual)" $ do
-          (innerReportContents, _) <- capture $ hspec $ [H.describe "" [ H.it "" (HUnit.assertEqual "trivial" (1::Int) 2)]]
-          let innerReport = lines innerReportContents
-          HUnit.assertBool "should find assertion text" $ any (=="trivial") innerReport
-          HUnit.assertBool "should find 'expected: 1'" $ any (=="expected: 1") innerReport
-          HUnit.assertBool "should find ' but got: 2'" $ any (==" but got: 2") innerReport
-
-    describe "QuickCheck property as an example" $ do
-        it "is specified with the \"property\" function"
-            (property $ \ b -> b || True)
-
-        it "will show what falsified it"
-            (any (=="0") report)
-
-    describe "pending as an example" $ do
-        it "is specified with the \"pending\" function and an explanation" True
-
-        it "accepts a message to display in the report" True
-
-    describe "the \"hHspecWithFormat\" function" $ do
-        it "can use the \"silent\" formatter to show no output"
-            (null silentReportContents)
-
-        it "can use the \"progress\" formatter to show '..F...FF.F' style output"
-            (HUnit.assertEqual "" ".F.FFF" (head $ lines progressReportContents))
-
-        it "can use the \"specdoc\" formatter to show all examples (default)"
-            (HUnit.assertEqual "" "Example" (lines reportContents !! 1))
-
-        it "can use the \"failed_examples\" formatter to show only failed examples"
-            (HUnit.assertEqual "" "1) Example fail 1 FAILED" (lines failed_examplesReportContents !! 1))
-
-    describe "quantify (an internal function)" $ do
-        it "returns an amount and a word given an amount and word"
-            (quantify (1::Int) "thing" == "1 thing")
-
-        it "returns a singular word given the number 1"
-            (quantify (1::Int) "thing" == "1 thing")
-
-        it "returns a plural word given a number greater than 1"
-            (quantify (2::Int) "thing" == "2 things")
-
-        it "returns a plural word given the number 0"
-            (quantify (0::Int) "thing" == "0 things")
diff --git a/Test/Hspec.hs b/Test/Hspec.hs
--- a/Test/Hspec.hs
+++ b/Test/Hspec.hs
@@ -1,3 +1,4 @@
+{-# OPTIONS_HADDOCK prune #-}
 -- |
 -- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is
 -- an approach to software development that combines Test-Driven Development,
@@ -34,14 +35,25 @@
 -- * Running a spec
 , hspec
 , hspecB
-, hspecX
 , hHspec
+, Summary (..)
 
--- * Deprecated functions
+
+
+
+
+-- deprecated functions
 , descriptions
+, hspecX
+
+
+
 ) where
 
 import           Test.Hspec.Core
+
+
+
 
 -- $intro
 --
diff --git a/Test/Hspec/Core.hs b/Test/Hspec/Core.hs
--- a/Test/Hspec/Core.hs
+++ b/Test/Hspec/Core.hs
@@ -1,8 +1,27 @@
-{-# OPTIONS_GHC -fno-warn-deprecations #-}
+{-# OPTIONS_HADDOCK prune #-}
 -- |
--- This module contains the core types, constructors, classes, instances, and
--- utility functions common to hspec.
+-- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is
+-- an approach to software development that combines Test-Driven Development,
+-- Domain Driven Design, and Acceptance Test-Driven Planning. Hspec helps you
+-- do the TDD part of that equation, focusing on the documentation and design
+-- aspects of TDD.
+--
+-- Hspec (and the preceding intro) are based on the Ruby library RSpec. Much of
+-- what applies to RSpec also applies to Hspec. Hspec ties together
+-- /descriptions/ of behavior and /examples/ of that behavior. The examples can
+-- also be run as tests and the output summarises what needs to be implemented.
+--
+-- NOTE: There is a monadic and a non-monadic API.  This is the documentation
+-- for the non-monadic API.  The monadic API is more stable, so you may prefer
+-- it over this one.  For documentation on the monadic API look at
+-- "Test.Hspec.Monadic".
+
 module Test.Hspec.Core (
+
+
+-- * Introduction
+-- $intro
+
 -- * Types
   Spec
 , Specs
@@ -17,29 +36,19 @@
 -- * Running a spec
 , hspec
 , hspecB
-, hspecX
 , hHspec
+, Summary (..)
 
 -- * Internals
-, SpecTree (..)
-, EvaluatedSpec
-, Result (..)
 , quantify
+, Result (..)
 
--- * Deprecated types and functions
--- | The following types and functions are deprecated and will be removed with
--- the next release.
---
--- If you still need any of those, please open an issue and describe your use
--- case: <https://github.com/hspec/hspec/issues>
+-- deprecated stuff
 , descriptions
+, hspecX
 , AnyExample
 , safeEvaluateExample
 , UnevaluatedSpec
-, success
-, failure
-, isFailure
-, failedCount
 ) where
 
 import           Test.Hspec.Internal hiding (safeEvaluateExample)
@@ -47,36 +56,85 @@
 import           Test.Hspec.Pending
 import           Test.Hspec.Runner
 
+-- $intro
+--
+-- The three functions you'll use the most are 'hspecX', 'describe', and 'it'.
+-- Here is an example of functions that format and unformat phone numbers and
+-- the specs for them.
+--
+-- > import Test.Hspec
+-- > import Test.Hspec.QuickCheck
+-- > import Test.Hspec.HUnit ()
+-- > import Test.QuickCheck
+-- > import Test.HUnit
+-- >
+-- > main = hspecX mySpecs
+--
+-- Since the specs are often used to tell you what to implement, it's best to
+-- start with undefined functions. Once we have some specs, then you can
+-- implement each behavior one at a time, ensuring that each behavior is met
+-- and there is no undocumented behavior.
+--
+-- > unformatPhoneNumber :: String -> String
+-- > unformatPhoneNumber number = undefined
+-- >
+-- > formatPhoneNumber :: String -> String
+-- > formatPhoneNumber number = undefined
+--
+-- The 'describe' function takes a list of behaviors and examples bound
+-- together with the 'it' function
+--
+-- > mySpecs = [describe "unformatPhoneNumber" [
+--
+-- A boolean expression can act as a behavior's example.
+--
+-- >   it "removes dashes, spaces, and parenthesies" $
+-- >     unformatPhoneNumber "(555) 555-1234" == "5555551234"
+-- >   ,
+--
+-- The 'pending' function marks a behavior as pending an example. The example
+-- doesn't count as failing.
+--
+-- >   it "handles non-US phone numbers" $
+-- >     pending "need to look up how other cultures format phone numbers"
+-- >   ,
+--
+-- An HUnit 'Test.HUnit.Test' can act as a behavior's example. (must import
+-- "Test.Hspec.HUnit")
+--
+-- >   it "removes the \"ext\" prefix of the extension" $ TestCase $ do
+-- >     let expected = "5555551234135"
+-- >         actual   = unformatPhoneNumber "(555) 555-1234 ext 135"
+-- >     expected @?= actual
+-- >   ,
+--
+-- An @IO()@ action is treated like an HUnit 'TestCase'. (must import
+-- "Test.Hspec.HUnit")
+--
+-- >   it "converts letters to numbers" $ do
+-- >     let expected = "6862377"
+-- >         actual   = unformatPhoneNumber "NUMBERS"
+-- >     actual @?= expected
+-- >   ,
+--
+-- The 'property' function allows a QuickCheck property to act as an example.
+-- (must import "Test.Hspec.QuickCheck")
+--
+-- >   it "can add and remove formatting without changing the number" $ property $
+-- >     forAll phoneNumber $ \n -> unformatPhoneNumber (formatPhoneNumber n) == n
+-- >   ]]
+-- >
+-- > phoneNumber :: Gen String
+-- > phoneNumber = do
+-- >   n <- elements [7,10,11,12,13,14,15]
+-- >   vectorOf n (elements "0123456789")
+
 {-# DEPRECATED UnevaluatedSpec "use Spec instead" #-}
 type UnevaluatedSpec = Spec
 
--- | DEPRECATED: This is no longer needed (it's just an alias for `id` now).
+{-# DEPRECATED descriptions "this is no longer needed, and will be removed in a future release" #-}
 descriptions :: Specs -> Specs
 descriptions = id
-{-# DEPRECATED descriptions "this is no longer needed, and will be removed in a future release" #-}
-
-{-# DEPRECATED success "This will be removed with the next major release.  If you still need this, raise your voice!" #-}
-success :: [EvaluatedSpec] -> Bool
-success = not . failure
-
-{-# DEPRECATED failure "This will be removed with the next major release.  If you still need this, raise your voice!" #-}
-failure :: [EvaluatedSpec] -> Bool
-failure = any p
-  where
-    p (SpecGroup _ xs) = any p xs
-    p (SpecExample _ x) = isFailure x
-
-{-# DEPRECATED isFailure "This will be removed with the next major release.  If you still need this, raise your voice!" #-}
-isFailure :: Result -> Bool
-isFailure (Fail _) = True
-isFailure _        = False
-
-{-# DEPRECATED failedCount "This will be removed with the next major release.  If you still need this, raise your voice!" #-}
-failedCount :: [EvaluatedSpec] -> Int
-failedCount = sum . map count
-  where
-    count (SpecGroup _ xs) = sum (map count xs)
-    count (SpecExample _ x) = if isFailure x then 1 else 0
 
 {-# DEPRECATED AnyExample "This will be removed with the next major release.  If you still need this, raise your voice!" #-}
 type AnyExample  = IO Result
diff --git a/Test/Hspec/Formatters.hs b/Test/Hspec/Formatters.hs
--- a/Test/Hspec/Formatters.hs
+++ b/Test/Hspec/Formatters.hs
@@ -43,6 +43,7 @@
 import           Data.List (intersperse)
 import           Text.Printf
 import           Control.Monad (unless)
+import           Control.Applicative
 
 -- We use an explicit import list for "Test.Hspec.Formatters.Internal", to make
 -- sure, that we only use the public API to implement formatters.
@@ -134,12 +135,12 @@
 
 defaultFooter :: FormatM ()
 defaultFooter = do
-  cpuTime <- getCPUTime
-  time <- getRealTime
+
+  writeLine =<< printf "Finished in %1.4f seconds, used %1.4f seconds of CPU time" <$> getRealTime <*> getCPUTime
+
   fails <- getFailCount
   total <- getTotalCount
   (if fails == 0 then withSuccessColor else withFailColor) $ do
-    writeLine $ printf "Finished in %1.4f seconds, used %1.4f seconds of CPU time" time cpuTime
     writeLine ""
     write $ quantify total "example" ++ ", "
     writeLine $ quantify fails "failure"
diff --git a/Test/Hspec/Formatters/Internal.hs b/Test/Hspec/Formatters/Internal.hs
--- a/Test/Hspec/Formatters/Internal.hs
+++ b/Test/Hspec/Formatters/Internal.hs
@@ -32,6 +32,7 @@
 import qualified System.IO as IO
 import           System.IO (Handle)
 import           Control.Monad (when)
+import           Control.Applicative
 import           Control.Exception (bracket_)
 import           System.Console.ANSI
 import           Control.Monad.Trans.State hiding (gets, modify)
@@ -72,7 +73,7 @@
 totalCount s = successCount s + pendingCount s + failCount s
 
 newtype FormatM a = FormatM (StateT FormatterState IO a)
-  deriving (Functor, Monad)
+  deriving (Functor, Applicative, Monad)
 
 runFormatM :: Bool -> Handle -> FormatM a -> IO a
 runFormatM useColor handle (FormatM action) = do
diff --git a/Test/Hspec/HUnit.hs b/Test/Hspec/HUnit.hs
--- a/Test/Hspec/HUnit.hs
+++ b/Test/Hspec/HUnit.hs
@@ -23,8 +23,7 @@
 -- >     it "gives the original list, if applied twice" $ TestCase $
 -- >       (reverse . reverse) [1, 2, 3] @?= [1, 2, 3]
 --
-module Test.Hspec.HUnit (
-) where
+module Test.Hspec.HUnit () where
 
 import           System.IO.Silently
 import           Test.Hspec.Core
@@ -41,6 +40,6 @@
              then Success
              else Fail (details $ fails "")
     return r
-
-details :: String -> String
-details = concat . intersperse "\n" . tail . init . lines
+    where
+      details :: String -> String
+      details = concat . intersperse "\n" . tail . init . lines
diff --git a/Test/Hspec/Internal.hs b/Test/Hspec/Internal.hs
--- a/Test/Hspec/Internal.hs
+++ b/Test/Hspec/Internal.hs
@@ -1,9 +1,6 @@
-{-# LANGUAGE FlexibleInstances #-}
 module Test.Hspec.Internal (
-  SpecTree (..)
-, Spec (..)
+  Spec (..)
 , Specs
-, EvaluatedSpec
 , Example (..)
 , safeEvaluateExample
 , Result (..)
@@ -16,37 +13,21 @@
 where
 
 import           Control.Exception
-import qualified Test.Hspec.Pending as Pending
 
+-- | A list of specs.
 type Specs = [Spec]
-type EvaluatedSpec = SpecTree Result
 
 -- | The result of running an example.
 data Result = Success | Pending (Maybe String) | Fail String
   deriving (Eq, Show)
 
-newtype Spec = Spec {unSpec :: SpecTree (IO Result)}
-
--- IMPORTANT: Remove this warnings and remove -fno-warn-deprecations from the
--- following modules/files when making SpecGroup abstract.
---
---  * Spec.hs
---  * Test.Hspec.Runner
---  * Test.Hspec.Core
---
-{-# WARNING SpecExample "This will be removed from the public interface with the next major release.  If you need this, raise your voice!" #-}
-{-# WARNING SpecGroup "This will be removed from the public interface with the next major release.  If you need this, raise your voice!" #-}
-
 -- | Internal representation of a spec.
---
--- This will be made abstract with the next release.  If you still need access
--- to any constructors, open an issue and describe your use case:
--- <https://github.com/hspec/hspec/issues>
-data SpecTree a = SpecGroup String [SpecTree a]
-            | SpecExample String a
+data Spec = SpecGroup String [Spec]
+          | SpecExample String (IO Result)
 
+-- | The @describe@ function combines a list of specs into a larger spec.
 describe :: String -> [Spec] -> Spec
-describe str specs = Spec . SpecGroup str $ map unSpec specs
+describe = SpecGroup
 
 safeEvaluateExample :: IO Result -> IO Result
 safeEvaluateExample action = do
@@ -70,7 +51,7 @@
 -- >   ]
 --
 it :: Example a => String -> a -> Spec
-it requirement' = Spec . SpecExample requirement' . evaluateExample
+it requirement = SpecExample requirement . evaluateExample
 
 -- | A type class for examples.
 --
@@ -88,13 +69,18 @@
 instance Example Result where
   evaluateExample r = r `seq` return r
 
-instance Example Pending.Pending where
-  evaluateExample (Pending.Pending reason) = evaluateExample (Pending reason)
-
-instance Example (String -> Pending.Pending) where
-  evaluateExample _ = evaluateExample (Pending.Pending Nothing)
-
 -- | Create a more readable display of a quantity of something.
-quantify :: (Show a, Num a, Eq a) => a -> String -> String
+--
+-- Examples:
+--
+-- >>> quantify 0 "example"
+-- "0 examples"
+--
+-- >>> quantify 1 "example"
+-- "1 example"
+--
+-- >>> quantify 2 "example"
+-- "2 examples"
+quantify :: Int -> String -> String
 quantify 1 s = "1 " ++ s
 quantify n s = show n ++ " " ++ s ++ "s"
diff --git a/Test/Hspec/Monadic.hs b/Test/Hspec/Monadic.hs
--- a/Test/Hspec/Monadic.hs
+++ b/Test/Hspec/Monadic.hs
@@ -1,11 +1,17 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# OPTIONS_HADDOCK prune #-}
+{-# OPTIONS_GHC -fno-warn-deprecations #-}
 -- |
--- There is a monadic and a non-monadic API.  This is the documentation for the
--- monadic API.  The monadic API is suitable for most use cases, and it is more
--- stable than the non-monadic API.
---
--- For documentation on the non-monadic API look at "Test.Hspec".
+-- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is
+-- an approach to software development that combines Test-Driven Development,
+-- Domain Driven Design, and Acceptance Test-Driven Planning. Hspec helps you
+-- do the TDD part of that equation, focusing on the documentation and design
+-- aspects of TDD.
 --
+-- Hspec (and the preceding intro) are based on the Ruby library RSpec. Much of
+-- what applies to RSpec also applies to Hspec. Hspec ties together
+-- /descriptions/ of behavior and /examples/ of that behavior. The examples can
+-- also be run as tests and the output summarises what needs to be implemented.
 module Test.Hspec.Monadic (
 -- * Introduction
 -- $intro
@@ -23,22 +29,24 @@
 -- * Running a spec
 , hspec
 , hspecB
-, hspecX
 , hHspec
+, Summary (..)
 
 -- * Interface to the non-monadic API
 , runSpecM
 , fromSpecList
 
--- * Deprecated types and functions
-, descriptions
+-- deprecated stuff
 , Specs
+, descriptions
+, hspecX
 ) where
 
 import           System.IO
-import           Test.Hspec.Core (EvaluatedSpec, Example)
+import           Test.Hspec.Core (Example)
 import qualified Test.Hspec.Core as Core
 import qualified Test.Hspec.Runner as Runner
+import           Test.Hspec.Runner (Summary (..))
 import           Test.Hspec.Pending (Pending)
 import qualified Test.Hspec.Pending as Pending
 
@@ -122,15 +130,16 @@
 newtype SpecM a = SpecM (Writer [Core.Spec] a)
   deriving Monad
 
--- | Create a document of the given specs and write it to stdout.
-hspec :: Spec -> IO [EvaluatedSpec]
+-- | Create a document of the given spec and write it to stdout.
+--
+-- Exit the program with `exitSuccess` if all examples passed, with
+-- `exitFailure` otherwise.
+hspec :: Spec -> IO ()
 hspec = Runner.hspec . runSpecM
 
--- | Use in place of `hspec` to also exit the program with an @ExitCode@
-hspecX :: Spec -> IO a
-hspecX = Runner.hspecX . runSpecM
-
--- | Use in place of hspec to also give a @Bool@ success indication
+-- | Create a document of the given spec and write it to stdout.
+--
+-- Return `True` if all examples passed, `False` otherwise.
 hspecB :: Spec -> IO Bool
 hspecB = Runner.hspecB . runSpecM
 
@@ -138,7 +147,7 @@
 --
 -- > writeReport filename specs = withFile filename WriteMode (\h -> hHspec h specs)
 --
-hHspec :: Handle -> Spec -> IO [EvaluatedSpec]
+hHspec :: Handle -> Spec -> IO Summary
 hHspec h = Runner.hHspec h . runSpecM
 
 -- | Convert a monadic spec into a non-monadic spec.
@@ -149,12 +158,21 @@
 fromSpecList :: [Core.Spec] -> Spec
 fromSpecList = SpecM . tell
 
+-- | The @describe@ function combines a list of specs into a larger spec.
 describe :: String -> Spec -> Spec
 describe label action = SpecM . tell $ [Core.describe label (runSpecM action)]
 
+-- | An alias for `describe`.
 context :: String -> Spec -> Spec
 context = describe
 
+-- |
+-- Create a set of specifications for a specific type being described.  Once
+-- you know what you want specs for, use this.
+--
+-- > describe "abs" $ do
+-- >   it "returns a positive number given a negative number" $
+-- >     abs (-1) == 1
 it :: Example v => String -> v -> Spec
 it label action = (SpecM . tell) [Core.it label action]
 
@@ -174,10 +192,13 @@
 pending :: String  -> Pending
 pending = Pending.pending
 
--- | DEPRECATED: Use `sequence_` instead.
+{-# DEPRECATED Specs "use Spec instead" #-}
+type Specs = SpecM ()
+
+{-# DEPRECATED descriptions "use sequence_ instead" #-}
 descriptions :: [Spec] -> Spec
 descriptions = sequence_
-{-# DEPRECATED descriptions "use sequence_ instead" #-}
 
--- | DEPRECATED: Use `Spec` instead
-type Specs = SpecM ()
+{-# DEPRECATED hspecX "use hspec instead" #-}
+hspecX :: Spec -> IO a
+hspecX = Runner.hspecX . runSpecM
diff --git a/Test/Hspec/Pending.hs b/Test/Hspec/Pending.hs
--- a/Test/Hspec/Pending.hs
+++ b/Test/Hspec/Pending.hs
@@ -1,6 +1,20 @@
+{-# LANGUAGE FlexibleInstances #-}
 module Test.Hspec.Pending where
 
+import qualified Test.Hspec.Internal as Internal
+import           Test.Hspec.Internal (Example(..))
+
+-- NOTE: This is defined in a separate packages, because it clashes with
+-- Result.Pending.
+
+-- | A pending example.
 newtype Pending = Pending (Maybe String)
+
+instance Example Pending where
+  evaluateExample (Pending reason) = evaluateExample (Internal.Pending reason)
+
+instance Example (String -> Pending) where
+  evaluateExample _ = evaluateExample (Pending Nothing)
 
 -- | A pending example.
 --
diff --git a/Test/Hspec/QuickCheck.hs b/Test/Hspec/QuickCheck.hs
--- a/Test/Hspec/QuickCheck.hs
+++ b/Test/Hspec/QuickCheck.hs
@@ -36,9 +36,9 @@
 instance Example QC.Property where
   evaluateExample p = do
     r <- silence $ QC.quickCheckResult p
-    let r' = case r of
-              QC.Success {}           -> Success
-              f@(QC.Failure {})       -> Fail (QC.output f)
-              g@(QC.GaveUp {})        -> Fail ("Gave up after " ++ quantify (QC.numTests g) "test" )
-              QC.NoExpectedFailure {} -> Fail ("No expected failure")
-    return r'
+    return $
+      case r of
+        QC.Success {}               -> Success
+        f@(QC.Failure {})           -> Fail (QC.output f)
+        QC.GaveUp {QC.numTests = n} -> Fail ("Gave up after " ++ quantify n "test" )
+        QC.NoExpectedFailure {}     -> Fail ("No expected failure")
diff --git a/Test/Hspec/Runner.hs b/Test/Hspec/Runner.hs
--- a/Test/Hspec/Runner.hs
+++ b/Test/Hspec/Runner.hs
@@ -1,11 +1,24 @@
-{-# OPTIONS_GHC -fno-warn-deprecations #-}
 -- | This module contains the runners that take a set of specs, evaluate their examples, and
 -- report to a given handle.
 --
 module Test.Hspec.Runner (
-  Specs, hspec, hspecX, hspecB, hHspec, hHspecWithFormat, describe, it, toExitCode
+  Specs
+, hspec
+, hspecB
+, hHspec
+, hHspecWithFormat
+, toExitCode
+
+, Summary (..)
+
+-- * Deprecated functions
+, hspecX
 ) where
 
+import           Control.Monad (unless, (>=>))
+import           Control.Applicative
+import           Data.Monoid
+
 import           Test.Hspec.Internal
 import           Test.Hspec.Formatters
 import           Test.Hspec.Formatters.Internal
@@ -13,13 +26,13 @@
 import           System.Exit
 
 -- | Evaluate and print the result of checking the spec examples.
-runFormatter :: Formatter -> Spec -> FormatM EvaluatedSpec
-runFormatter formatter = go 0 [] . unSpec
+runFormatter :: Formatter -> Spec -> FormatM ()
+runFormatter formatter = go 0 []
   where
+    go :: Int -> [String] -> Spec -> FormatM ()
     go nesting groups (SpecGroup group xs) = do
       exampleGroupStarted formatter nesting group
-      ys <- mapM (go (succ nesting) (group : groups)) xs
-      return (SpecGroup group ys)
+      mapM_ (go (succ nesting) (group : groups)) xs
     go nesting groups (SpecExample requirement e) = do
       result <- liftIO $ safeEvaluateExample e
       case result of
@@ -34,7 +47,6 @@
         Pending reason -> do
           increasePendingCount
           examplePending formatter nesting requirement reason
-      return (SpecExample requirement result)
 
 failureDetails :: [String] -> String -> String -> Int -> String
 failureDetails groups requirement err i =
@@ -48,49 +60,54 @@
       _   -> concatMap (++ " - ") (reverse groups)
 
 
--- | Use in place of `hspec` to also exit the program with an @ExitCode@
+-- | Create a document of the given specs and write it to stdout.
+--
+-- Exit the program with `exitSuccess` if all examples passed, with
+-- `exitFailure` otherwise.
+hspec :: Specs -> IO ()
+hspec = hspecB >=> (`unless` exitFailure)
+
+{-# DEPRECATED hspecX "use hspec instead" #-}
 hspecX :: Specs -> IO a
-hspecX ss = hspecB ss >>= exitWith . toExitCode
+hspecX = hspecB >=> exitWith . toExitCode
 
--- | Use in place of hspec to also give a @Bool@ success indication
+-- | Create a document of the given specs and write it to stdout.
+--
+-- Return `True` if all examples passed, `False` otherwise.
 hspecB :: Specs -> IO Bool
-hspecB ss = success `fmap` hspec ss
+hspecB = fmap success . hHspec stdout
   where
-    success :: [EvaluatedSpec] -> Bool
-    success = not . failure
-
-    failure :: [EvaluatedSpec] -> Bool
-    failure = any p
-      where
-        p (SpecGroup _ xs) = any p xs
-        p (SpecExample _ x) = isFailure x
-
-    isFailure :: Result -> Bool
-    isFailure (Fail _) = True
-    isFailure _        = False
-
--- | Create a document of the given specs and write it to stdout.
-hspec :: Specs -> IO [EvaluatedSpec]
-hspec = hHspec stdout
+    success :: Summary -> Bool
+    success s = summaryFailures s == 0
 
 -- | Create a document of the given specs and write it to the given handle.
 --
 -- > writeReport filename specs = withFile filename WriteMode (\h -> hHspec h specs)
 --
-hHspec :: Handle -> Specs -> IO [EvaluatedSpec]
+hHspec :: Handle -> Specs -> IO Summary
 hHspec h specs = do
   useColor <- hIsTerminalDevice h
   hHspecWithFormat specdoc useColor h specs
 
 -- | Create a document of the given specs and write it to the given handle.
 -- THIS IS LIKELY TO CHANGE
-hHspecWithFormat :: Formatter -> Bool -> Handle -> Specs -> IO [EvaluatedSpec]
+hHspecWithFormat :: Formatter -> Bool -> Handle -> Specs -> IO Summary
 hHspecWithFormat formatter useColor h ss = runFormatM useColor h $ do
-  specList <- mapM (runFormatter formatter) ss
+  mapM_ (runFormatter formatter) ss
   failedFormatter formatter
   footerFormatter formatter
-  return specList
+  Summary <$> getTotalCount <*> getFailCount
 
 toExitCode :: Bool -> ExitCode
 toExitCode True  = ExitSuccess
 toExitCode False = ExitFailure 1
+
+-- | Summary of a test run.
+data Summary = Summary {
+  summaryExamples :: Int
+, summaryFailures :: Int
+} deriving (Eq, Show)
+
+instance Monoid Summary where
+  mempty = Summary 0 0
+  (Summary x1 x2) `mappend` (Summary y1 y2) = Summary (x1 + y1) (x2 + y2)
diff --git a/example/NonMonadic.hs b/example/NonMonadic.hs
new file mode 100644
--- /dev/null
+++ b/example/NonMonadic.hs
@@ -0,0 +1,23 @@
+module Main (main, spec) where
+
+import Test.Hspec.Core
+import Test.Hspec.HUnit ()
+import Test.Hspec.QuickCheck
+import Test.HUnit
+
+shouldBe :: (Show a, Eq a) => a -> a -> Assertion
+actual `shouldBe` expected = actual @?= expected
+
+main :: IO ()
+main = hspec spec
+
+spec :: Specs
+spec = [
+    describe "reverse" [
+      it "reverses a list" $ do
+        reverse [1 :: Int, 2, 3] `shouldBe` [3, 2, 1]
+
+    , it "gives the original list, if applied twice" $ property $
+        \(xs) -> reverse (reverse xs) == (xs :: [Int])
+    ]
+  ]
diff --git a/example/Spec.hs b/example/Spec.hs
new file mode 100644
--- /dev/null
+++ b/example/Spec.hs
@@ -0,0 +1,21 @@
+module Main (main, spec) where
+
+import Test.Hspec.Monadic
+import Test.Hspec.HUnit ()
+import Test.Hspec.QuickCheck
+import Test.HUnit
+
+shouldBe :: (Show a, Eq a) => a -> a -> Assertion
+actual `shouldBe` expected = actual @?= expected
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = do
+  describe "reverse" $ do
+    it "reverses a list" $ do
+      reverse [1 :: Int, 2, 3] `shouldBe` [3, 2, 1]
+
+    it "gives the original list, if applied twice" $ property $
+      \xs -> reverse (reverse xs) == (xs :: [Int])
diff --git a/hspec.cabal b/hspec.cabal
--- a/hspec.cabal
+++ b/hspec.cabal
@@ -1,26 +1,26 @@
-name:           hspec
-version:        1.1.3
-cabal-version:  >= 1.8
-build-type:     Simple
-license:        BSD3
-license-file:   LICENSE
-copyright:      (c) 2011 Trystan Spangler
-category:       Testing
-author:         Trystan Spangler
-maintainer:     trystan.s@comcast.net
-stability:      experimental
-bug-reports:    https://github.com/hspec/hspec/issues
-homepage:       http://hspec.github.com/
-synopsis:       Behavior Driven Development for Haskell
-description:    Behavior Driven Development for Haskell
-                .
-                Hspec is roughly based on the Ruby library RSpec. However,
-                Hspec is just a framework for running HUnit and QuickCheck
-                tests. Compared to other options, it provides a much nicer
-                syntax that makes tests very easy to read.
-                .
-                New to Hspec?  Start with the introductory documentation:
-                <http://hspec.github.com/>
+name:             hspec
+version:          1.2.0
+license:          BSD3
+license-file:     LICENSE
+copyright:        (c) 2011 Trystan Spangler
+author:           Trystan Spangler
+maintainer:       trystan.s@comcast.net
+build-type:       Simple
+cabal-version:    >= 1.8
+category:         Testing
+stability:        experimental
+bug-reports:      https://github.com/hspec/hspec/issues
+homepage:         http://hspec.github.com/
+synopsis:         Behavior Driven Development for Haskell
+description:      Behavior Driven Development for Haskell
+                  .
+                  Hspec is roughly based on the Ruby library RSpec. However,
+                  Hspec is just a framework for running HUnit and QuickCheck
+                  tests. Compared to other options, it provides a much nicer
+                  syntax that makes tests very easy to read.
+                  .
+                  Start with the introductory documentation:
+                  <http://hspec.github.com/>
 
 source-repository head
   type: git
@@ -71,21 +71,45 @@
     , HUnit >= 1 && <= 2
     , QuickCheck >= 2.4.0.1 && <= 2.5
     , hspec-shouldbe
+    , hspec-discover
 
--- this should be merged with spec
-test-suite old-spec
+test-suite doctests
+  main-is:
+      doctests.hs
   type:
       exitcode-stdio-1.0
+  ghc-options:
+      -Wall -Werror -threaded
+  hs-source-dirs:
+      test
+  build-depends:
+      base
+    , doctest >= 0.7
+
+test-suite example
+  type:
+      exitcode-stdio-1.0
   main-is:
-      Specs.hs
+      Spec.hs
+  hs-source-dirs:
+      example
   ghc-options:
       -Wall -Werror
   build-depends:
-      base >= 4 && <= 5
-    , silently >= 1.1.1 && < 2
-    , ansi-terminal == 0.5.5
-    , time < 1.5
-    , transformers >= 0.2.0 && < 0.4.0
-    , HUnit >= 1 && <= 2
-    , QuickCheck >= 2.4.0.1 && <= 2.5
-    , hspec-shouldbe
+      base
+    , hspec
+    , HUnit
+
+test-suite example-non-monadic
+  type:
+      exitcode-stdio-1.0
+  main-is:
+      NonMonadic.hs
+  hs-source-dirs:
+      example
+  ghc-options:
+      -Wall -Werror
+  build-depends:
+      base
+    , hspec
+    , HUnit
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,9 +1,1 @@
-module Main (main) where
-
-import           Test.Hspec.ShouldBe
-
-import qualified Test.Hspec.MonadicSpec
-
-main :: IO ()
-main = hspecX $ do
-  describe "Test.Hspec.Monadic" Test.Hspec.MonadicSpec.spec
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/test/doctests.hs b/test/doctests.hs
new file mode 100644
--- /dev/null
+++ b/test/doctests.hs
@@ -0,0 +1,6 @@
+module Main where
+
+import           Test.DocTest
+
+main :: IO ()
+main = doctest ["Test/Hspec/Internal.hs"]
