module Hedgehog.Internal.Exception ( TypedException(..) , tryAll ) where import Control.Exception (Exception(..), AsyncException, SomeException(..)) import Control.Monad.Catch (MonadCatch(..), throwM) import Data.Typeable (typeOf) -- | Newtype for 'SomeException' with a 'Show' instance that only contains -- valid Haskell 98 tokens and also includes the type of the exception. -- -- For example, when catching the exception thrown by @fail "foo" :: IO ()@ -- and calling show: -- -- @ -- IOException "user error (foo)" -- @ -- -- Having access to the type can be useful when trying to track down the -- source of an exception. -- newtype TypedException = TypedException SomeException instance Show TypedException where showsPrec p (TypedException (SomeException x)) = showParen (p > 10) $ showsPrec 11 (typeOf x) . showChar ' ' . showsPrec 11 (displayException x) tryAll :: MonadCatch m => m a -> m (Either TypedException a) tryAll m = catch (fmap Right m) $ \exception -> case fromException exception :: Maybe AsyncException of Nothing -> pure . Left $ TypedException exception Just async -> throwM async