{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE Rank2Types #-} --------------------------------------------------------- -- -- Module : Control.Monad.Attempt.Class -- Copyright : Michael Snoyman -- License : BSD3 -- -- Maintainer : Michael Snoyman <michael@snoyman.com> -- Stability : Unstable -- Portability : portable -- --------------------------------------------------------- -- | Defines a type class for any monads which may report failure using -- extensible exceptions. module Control.Monad.Attempt.Class ( MonadAttempt (..) , StringException (..) ) where import Control.Exception import Data.Generics -- | Any 'Monad' which may report failure using extensible exceptions. This -- most obviously applies to the Attempt data type, but you should just as well -- use this for arbitrary 'Monad's. -- -- Usage should be straight forward: 'return' successes and 'failure' errors. -- If you simply want to send a string error message, use 'failureString'. -- Although tempting to do so, 'fail' is *not* used as a synonym for -- 'failureString'; 'fail' should not be used at all. -- -- Minimal complete definition: 'failure' and 'wrapFailure'. class Monad m => MonadAttempt m where failure :: Exception e => e -> m v -- | Call 'failure' by wrapping the argument in a 'StringException'. failureString :: String -> m v failureString = failure . StringException -- | Wrap the failure value, if any, with the given function. This is -- useful in particular when you want all the exceptions returned from a -- certain library to be of a certain type, even if they were generated by -- a different library. wrapFailure :: Exception eOut => (forall eIn. Exception eIn => eIn -> eOut) -> m v -> m v -- | A simple exception which simply contains a string. Note that the 'Show' -- instance simply returns the contained string. newtype StringException = StringException String deriving Typeable instance Show StringException where show (StringException s) = s instance Exception StringException