    {-# LANGUAGE CPP #-}
    -- |
    -- Experimental combinators, that may become part of the main distribution, if
    -- they turn out to be useful for a wider audience.
    module Test.Hspec.Expectations.Contrib (
    -- * Predicates
    -- | (useful in combination with `shouldSatisfy`)
      isLeft
    , isRight

    -- * Annotating expectations
    , annotate
    ) where

    import Control.Exception
    import Test.HUnit.Lang (HUnitFailure(..), FailureReason(..))

    #if MIN_VERSION_base(4,7,0)
    import Data.Either
    #else

    isLeft :: Either a b -> Bool
    {-# DEPRECATED isLeft "use Data.Either.Compat.isLeft from package base-compat instead" #-}
    isLeft (Left  _) = True
    isLeft (Right _) = False

    isRight :: Either a b -> Bool
    {-# DEPRECATED isRight "use Data.Either.Compat.isRight from package base-compat instead" #-}
    isRight (Left  _) = False
    isRight (Right _) = True
    #endif

    -- |
    -- If you have a test case that has multiple assertions, you can use the
    -- 'annotate' function to provide a string message that will be attached to
    -- the 'Expectation'.
    --
    -- @
    -- describe "annotate" $ do
    --   it "adds the message" $ do
    --     annotate "obvious falsehood" $ do
    --       True `shouldBe` False
    --
    -- ========>
    --
    -- 1) annotate, adds the message
    --       obvious falsehood
    --       expected: False
    --        but got: True
    -- @
    --
    -- @since 0.8.3
    annotate :: String -> IO a -> IO a
    annotate :: forall a. String -> IO a -> IO a
    annotate String
    message = (HUnitFailure -> IO a) -> IO a -> IO a
    forall e a. Exception e => (e -> IO a) -> IO a -> IO a
    handle ((HUnitFailure -> IO a) -> IO a -> IO a)
    -> (HUnitFailure -> IO a) -> IO a -> IO a
    forall a b. (a -> b) -> a -> b
    $ \ (HUnitFailure Maybe SrcLoc
    loc FailureReason
    reason) -> HUnitFailure -> IO a
    forall e a. Exception e => e -> IO a
    throwIO (HUnitFailure -> IO a)
    -> (FailureReason -> HUnitFailure) -> FailureReason -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Maybe SrcLoc -> FailureReason -> HUnitFailure
    HUnitFailure Maybe SrcLoc
    loc (FailureReason -> IO a) -> FailureReason -> IO a
    forall a b. (a -> b) -> a -> b
    $ case FailureReason
    reason of
      Reason String
    err -> String -> FailureReason
    Reason (String -> FailureReason) -> String -> FailureReason
    forall a b. (a -> b) -> a -> b
    $ String -> String
    addMessage String
    err
      ExpectedButGot Maybe String
    err String
    expected String
    got -> Maybe String -> String -> String -> FailureReason
    ExpectedButGot (String -> Maybe String
    forall a. a -> Maybe a
    Just (String -> Maybe String) -> String -> Maybe String
    forall a b. (a -> b) -> a -> b
    $ String -> (String -> String) -> Maybe String -> String
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe String
    message String -> String
    addMessage Maybe String
    err) String
    expected String
    got
      where
        addMessage :: String -> String
    addMessage String
    err
          | String -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null String
    err = String
    message
          | Bool
    otherwise = String
    message String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    "\n" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    err