packages feed

attempt 0.0.1 → 0.0.2

raw patch · 3 files changed

+57/−29 lines, 3 filesdep +monadlocdep ~control-monad-failure

Dependencies added: monadloc

Dependency ranges changed: control-monad-failure

Files

Control/Monad/Attempt.hs view
@@ -24,7 +24,8 @@ import Control.Applicative import Control.Monad import Control.Monad.Trans-import Control.Exception (Exception, SomeException (..))+import Control.Monad.Loc+import Control.Exception (Exception)  newtype AttemptT m v = AttemptT {     runAttemptT :: m (Attempt v)@@ -36,22 +37,24 @@     pure = return     (<*>) = ap instance Monad m => Monad (AttemptT m) where-    return = AttemptT . return . Success+    return = AttemptT . return . return     (AttemptT mv) >>= f = AttemptT $ do         v <- mv-        case v of-            Success v' -> runAttemptT $ f v'-            Failure e -> return $ Failure e+        attempt (return . failure) (runAttemptT . f) v instance (Exception e, Monad m) => MonadFailure e (AttemptT m) where-    failure = AttemptT . return . Failure . SomeException+    failure = AttemptT . return . failure instance (Monad m, Exception e) => WrapFailure e (AttemptT m) where     wrapFailure f (AttemptT mv) = AttemptT $ liftM (wrapFailure f) mv instance MonadTrans AttemptT where-    lift = AttemptT . liftM Success where+    lift = AttemptT . liftM return where instance MonadIO m => MonadIO (AttemptT m) where-    liftIO = AttemptT . liftM Success . liftIO where+    liftIO = AttemptT . liftM return . liftIO where instance Monad m => FromAttempt (AttemptT m) where     fromAttempt = attempt failure return+instance MonadLoc m => MonadLoc (AttemptT m) where+    withLoc loc (AttemptT a) = AttemptT $ do+        current <- withLoc loc a+        return $ withLoc loc current  -- | Instances of 'FromAttempt' specify a manner for embedding 'Attempt' -- failures directly into the target data type. For example, the 'IO' instance
Data/Attempt.hs view
@@ -22,10 +22,11 @@ -- might be a more appropriate fit. module Data.Attempt     ( -- * Data type and type class-      Attempt (..)+      Attempt     , FromAttempt (..)     , fa     , joinAttempt+    , monadicStackTrace       -- * General handling of 'Attempt's     , attempt     , makeHandler@@ -48,29 +49,40 @@ import Data.Generics import Data.Either (lefts) import Control.Monad.Failure-+import Control.Monad.Loc+import GHC.Show (appPrec, appPrec1) -- | Contains either a 'Success' value or a 'Failure' exception.-data Attempt v =-    Success v-    | Failure E.SomeException-    deriving (Show, Typeable)+data Attempt v+  = Success v+  | forall e. E.Exception e => Failure [String] e+    deriving (Typeable) +instance Show v => Show (Attempt v) where+  showsPrec p (Success v)+    = showParen (p > appPrec) $ showString "Success " . showsPrec appPrec1 v+  showsPrec p (Failure st v)+    = showParen (p > appPrec) $+        showString "Failure " . showsPrec appPrec1 st . showString " "+                              . showsPrec appPrec1 v+ instance Functor Attempt where     fmap f (Success v) = Success $ f v-    fmap _ (Failure e) = Failure e+    fmap _ (Failure st e) = Failure st e instance Applicative Attempt where     pure = Success     (<*>) = ap instance Monad Attempt where     return = Success     (Success v) >>= f = f v-    (Failure e) >>= _ = Failure e+    (Failure st e) >>= _ = Failure st e instance E.Exception e => MonadFailure e Attempt where-    failure = Failure . E.SomeException+    failure = Failure [] instance E.Exception e => WrapFailure e Attempt where     wrapFailure _ (Success v) = Success v-    wrapFailure f (Failure (E.SomeException e)) =-        Failure $ E.SomeException $ f e+    wrapFailure f (Failure st e) = Failure st $ f e+instance MonadLoc Attempt where+    withLoc _ (Success v) = Success v+    withLoc s (Failure st e) = Failure (s:st) e  -- | Any type which can be converted from an 'Attempt'. The included instances are your \"usual suspects\" for dealing with error handling. They include: --@@ -102,7 +114,7 @@ instance FromAttempt (Either String) where     fromAttempt = attempt (Left . show) Right instance FromAttempt (Either E.SomeException) where-    fromAttempt = attempt (Left . E.SomeException) Right+    fromAttempt = attempt (Left . E.toException) Right  -- | This is not a simple translation of the Control.Monad.join function. -- Instead, for 'Monad's which are instances of 'FromAttempt', it removes the@@ -113,36 +125,48 @@ joinAttempt :: (FromAttempt m, Monad m) => m (Attempt v) -> m v joinAttempt = (>>= fromAttempt) +-- | Extra the monadic stack trace from the given 'Attempt' value. Returns the+-- empty list when the given value is a 'Success'.+monadicStackTrace :: Attempt a -> [String]+monadicStackTrace (Success _) = []+monadicStackTrace (Failure st _) = st+ -- | Process either the exception or value in an 'Attempt' to produce a result. -- -- This function is modeled after 'maybe' and 'either'. The first argument must -- accept any instances of 'E.Exception'. If you want to handle multiple types -- of exceptions, see 'makeHandler'. The second argument converts the success -- value.+--+-- Note that this function does not expose all the data available in an+-- 'Attempt' value. Notably, the monadic stack trace is not passed on to the+-- error handler. If desired, use the 'monadicStackTrace' function to extract+-- it. attempt :: (forall e. E.Exception e => e -> b) -- ^ error handler         -> (a -> b) -- ^ success handler         -> Attempt a         -> b attempt _ f (Success v) = f v-attempt f _ (Failure e) = f e+attempt f _ (Failure _ e) = f e  -- | Convert multiple 'AttemptHandler's and a default value into an exception -- handler. -- -- This is a convenience function when you want to have special handling for a -- few types of 'E.Exception's and provide another value for anything else.-makeHandler :: [AttemptHandler v] -> v -> (forall e. E.Exception e => e -> v)+makeHandler :: [AttemptHandler v]+            -> v+            -> (forall e. E.Exception e => e -> v) makeHandler [] v _ = v makeHandler (AttemptHandler h:hs) v e =-    case cast e of-        Nothing -> makeHandler hs v e+    case E.fromException (E.toException e) of         Just e' -> h e'+        Nothing -> makeHandler hs v e  -- | A simple wrapper value necesary due to the Haskell type system. Wraps a -- function from a *specific* 'E.Exception' type to some value. data AttemptHandler v = forall e. E.Exception e => AttemptHandler (e -> v) - -- | Tests for a 'Failure' value. isFailure :: Attempt v -> Bool isFailure = attempt (const True) (const False)@@ -171,5 +195,5 @@ partitionAttempts :: [Attempt v] -> ([E.SomeException], [v]) partitionAttempts = foldr (attempt f s) ([],[])  where-  f a (l, r) = (E.SomeException a:l, r)+  f a (l, r) = (E.toException a:l, r)   s a (l, r) = (l, a:r)
attempt.cabal view
@@ -1,8 +1,8 @@ name:            attempt-version:         0.0.1+version:         0.0.2 license:         BSD3 license-file:    LICENSE-author:          Michael Snoyman <michael@snoyman.com>+author:          Michael Snoyman, Nicolas Pouillard maintainer:      Michael Snoyman <michael@snoyman.com> synopsis:        Error handling using extensible exceptions outside the IO monad. description:     Defines a data type, Attempt, which has a Success and Failure constructor. Failure contains an extensible exception.@@ -16,7 +16,8 @@     build-depends:   base >= 4 && < 5,                      syb,                      transformers >= 0.1.4.0,-                     control-monad-failure >= 0.2+                     control-monad-failure >= 0.4,+                     monadloc >= 0.4     exposed-modules: Data.Attempt                      Control.Monad.Attempt     ghc-options:     -Wall