packages feed

attempt 0.3.1.1 → 0.4.0.1

raw patch · 4 files changed

Files

Data/Attempt.hs view
@@ -1,209 +1,205 @@-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE TypeFamilies #-}
-
----------------------------------------------------------
---
--- Module        : Data.Attempt
--- Copyright     : Michael Snoyman
--- License       : BSD3
---
--- Maintainer    : Michael Snoyman <michael@snoyman.com>
--- Stability     : Unstable
--- Portability   : portable
---
--- A universal data type for computations which may fail.
----------------------------------------------------------
-
--- | A universal data type for computations which may fail. Errors are reported
--- using extensible exceptions. These exceptions are not explicitly stated; if
--- you want this kind of functionality, something like control-monad-exception
--- might be a more appropriate fit.
-module Data.Attempt
-    ( -- * Data type and type class
-      Attempt (..)
-    , FromAttempt (..)
-    , fa
-    , joinAttempt
-      -- * General handling of 'Attempt's
-    , attempt
-    , makeHandler
-    , AttemptHandler (..)
-      -- * Individual 'Attempt's
-    , isFailure
-    , isSuccess
-    , fromSuccess
-      -- * Lists of 'Attempt's
-    , successes
-    , failures
-    , partitionAttempts
-      -- * Runtime exceptions
-    , attemptIO
-      -- * Reexport the 'Failure' class
-    , module Control.Failure
-    ) where
-
-import qualified Control.Exception as E
-import Control.Monad (ap)
-import Control.Applicative
-import Data.Data
-import Data.Either (lefts)
-import Control.Failure
-import GHC.Show (appPrec, appPrec1)
--- | Contains either a 'Success' value or a 'Failure' exception.
-data Attempt v
-  = Success v
-  | forall e. E.Exception e => Failure 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 v)
-    = showParen (p > appPrec) $
-        showString "Failure " . showsPrec appPrec1 v
-
-instance Functor Attempt where
-    fmap f (Success v) = Success $ f v
-    fmap _ (Failure e) = Failure e
-instance Applicative Attempt where
-    pure = Success
-    (<*>) = ap
-instance Monad Attempt where
-    return = Success
-    (Success v) >>= f = f v
-    (Failure e) >>= _ = Failure e
-instance E.Exception e => Failure e Attempt where
-    failure = Failure
-instance E.Exception e => WrapFailure e Attempt where
-    wrapFailure _ (Success v) = Success v
-    wrapFailure f (Failure e) = Failure $ f e
-
-instance Try Attempt where
-    type Error Attempt = E.SomeException
-    try (Success v) = return v
-    try (Failure e) = failure $ E.toException e
-
--- | Any type which can be converted from an 'Attempt'. The included instances are your \"usual suspects\" for dealing with error handling. They include:
---
--- 'IO': For the IO instance, any exceptions in the 'Attempt' are thrown as
--- runtime exceptions.
---
--- 'Maybe': Returns 'Nothing' on 'Failure', or 'Just' on 'Success'.
---
--- List: Returns the empty list on 'Failure', or a singleton list on 'Success'.
---
--- 'Either' 'String': Returns 'Left' ('show' exception) on 'Failure', or 'Right' on
--- 'Success'.
---
--- 'Either' 'E.Exception': Returns 'Left' exception on 'Failure', or 'Right' on
--- 'Success'.
-class FromAttempt a where
-    fromAttempt :: Attempt v -> a v
-
--- | A shortcut for 'fromAttempt'.
-fa :: FromAttempt a => Attempt v -> a v
-fa = fromAttempt
-
-instance FromAttempt IO where
-    fromAttempt = attempt E.throwIO return
-instance FromAttempt Maybe where
-    fromAttempt = attempt (const Nothing) Just
-instance FromAttempt [] where
-    fromAttempt = attempt (const []) (: [])
-instance FromAttempt (Either String) where
-    fromAttempt = attempt (Left . show) Right
-instance FromAttempt (Either E.SomeException) where
-    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
--- inner 'Attempt' type, reporting errors as defined in the 'FromAttempt'
--- instance.
---
--- For example, join (Just (failureString \"foo\")) == Nothing.
-joinAttempt :: (FromAttempt m, Monad m) => m (Attempt v) -> m v
-joinAttempt = (>>= fromAttempt)
-
--- | 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
-
--- | 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 [] v _ = v
-makeHandler (AttemptHandler h: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)
-
--- | Tests for a 'Success' value.
-isSuccess :: Attempt v -> Bool
-isSuccess = attempt (const False) (const True)
-
--- | This is an unsafe, partial function which should only be used if you
--- either know that a function will succeed or don't mind the occassional
--- runtime exception.
-fromSuccess :: Attempt v -> v
-fromSuccess = attempt (error . show) id
-
--- | Returns only the 'Success' values.
-successes :: [Attempt v] -> [v]
-successes l = [ v | Success v <- l ]
-
--- | Returns only the 'Failure' values, each wrapped in a 'SomeException'.
-failures :: [Attempt v] -> [E.SomeException]
-failures = lefts . map eitherExceptionFromAttempt where
-    eitherExceptionFromAttempt :: Attempt v -> Either E.SomeException v
-    eitherExceptionFromAttempt = fa
-
--- | Return all of the 'Failure's and 'Success'es separately in a tuple.
-partitionAttempts :: [Attempt v] -> ([E.SomeException], [v])
-partitionAttempts = foldr (attempt f s) ([],[])
- where
-  f :: E.Exception e => e -> ([E.SomeException], [v]) -> ([E.SomeException], [v])
-  f a (l, r) = (E.toException a:l, r)
-  s a (l, r) = (l, a:r)
-
--- | Catches runtime (ie, IO) exceptions and inserts them into an 'Attempt'.
---
--- Like 'handle', the first argument to this function must explicitly state the
--- type of its input.
-attemptIO :: (E.Exception eIn, E.Exception eOut)
-          => (eIn -> eOut)
-          -> IO v
-          -> IO (Attempt v)
-attemptIO f =
-      E.handle (return . Failure . f)
-    . fmap Success
+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeFamilies #-}++---------------------------------------------------------+--+-- Module        : Data.Attempt+-- Copyright     : Michael Snoyman+-- License       : BSD3+--+-- Maintainer    : Michael Snoyman <michael@snoyman.com>+-- Stability     : Unstable+-- Portability   : portable+--+-- A universal data type for computations which may fail.+---------------------------------------------------------++-- | A universal data type for computations which may fail. Errors are reported+-- using extensible exceptions. These exceptions are not explicitly stated; if+-- you want this kind of functionality, something like control-monad-exception+-- might be a more appropriate fit.+module Data.Attempt+    ( -- * Data type and type class+      Attempt (..)+    , FromAttempt (..)+    , fa+    , joinAttempt+      -- * General handling of 'Attempt's+    , attempt+    , makeHandler+    , AttemptHandler (..)+      -- * Individual 'Attempt's+    , isFailure+    , isSuccess+    , fromSuccess+      -- * Lists of 'Attempt's+    , successes+    , failures+    , partitionAttempts+      -- * Runtime exceptions+    , attemptIO+      -- * Reexport the 'Failure' class+    , module Control.Failure+    ) where++import qualified Control.Exception as E+import Control.Monad (ap)+import Control.Applicative+import Data.Data+import Data.Either (lefts)+import Control.Failure+import GHC.Show (appPrec, appPrec1)+-- | Contains either a 'Success' value or a 'Failure' exception.+data Attempt v+  = Success v+  | forall e. E.Exception e => Failure 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 v)+    = showParen (p > appPrec) $+        showString "Failure " . showsPrec appPrec1 v++instance Functor Attempt where+    fmap f (Success v) = Success $ f v+    fmap _ (Failure e) = Failure e+instance Applicative Attempt where+    pure = Success+    (<*>) = ap+instance Monad Attempt where+    return = Success+    (Success v) >>= f = f v+    (Failure e) >>= _ = Failure e+instance E.Exception e => Failure e Attempt where+    failure = Failure++-- | Any type which can be converted from an 'Attempt'. The included instances are your \"usual suspects\" for dealing with error handling. They include:+--+-- 'IO': For the IO instance, any exceptions in the 'Attempt' are thrown as+-- runtime exceptions.+--+-- 'Maybe': Returns 'Nothing' on 'Failure', or 'Just' on 'Success'.+--+-- List: Returns the empty list on 'Failure', or a singleton list on 'Success'.+--+-- 'Either' 'String': Returns 'Left' ('show' exception) on 'Failure', or 'Right' on+-- 'Success'.+--+-- 'Either' 'E.Exception': Returns 'Left' exception on 'Failure', or 'Right' on+-- 'Success'.+class FromAttempt a where+    fromAttempt :: Attempt v -> a v++-- | A shortcut for 'fromAttempt'.+fa :: FromAttempt a => Attempt v -> a v+fa = fromAttempt++instance FromAttempt IO where+    fromAttempt = attempt E.throwIO return+instance FromAttempt Maybe where+    fromAttempt = attempt (const Nothing) Just+instance FromAttempt [] where+    fromAttempt = attempt (const []) (: [])+instance FromAttempt (Either String) where+    fromAttempt = attempt (Left . show) Right+instance FromAttempt (Either E.SomeException) where+    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+-- inner 'Attempt' type, reporting errors as defined in the 'FromAttempt'+-- instance.+--+-- For example, join (Just (failureString \"foo\")) == Nothing.+joinAttempt :: (FromAttempt m, Monad m) => m (Attempt v) -> m v+joinAttempt = (>>= fromAttempt)++-- | 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++-- | 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 [] v _ = v+makeHandler (AttemptHandler h: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)++-- | Tests for a 'Success' value.+isSuccess :: Attempt v -> Bool+isSuccess = attempt (const False) (const True)++-- | This is an unsafe, partial function which should only be used if you+-- either know that a function will succeed or don't mind the occassional+-- runtime exception.+fromSuccess :: Attempt v -> v+fromSuccess = attempt (error . show) id++-- | Returns only the 'Success' values.+successes :: [Attempt v] -> [v]+successes l = [ v | Success v <- l ]++-- | Returns only the 'Failure' values, each wrapped in a 'SomeException'.+failures :: [Attempt v] -> [E.SomeException]+failures = lefts . map eitherExceptionFromAttempt where+    eitherExceptionFromAttempt :: Attempt v -> Either E.SomeException v+    eitherExceptionFromAttempt = fa++-- | Return all of the 'Failure's and 'Success'es separately in a tuple.+partitionAttempts :: [Attempt v] -> ([E.SomeException], [v])+partitionAttempts =+    foldr (attempt f s) ([],[])+  where+    f :: E.Exception e+      => e+      -> ([E.SomeException], [v])+      -> ([E.SomeException], [v])+    f a (l, r) = (E.toException a:l, r)+    s a (l, r) = (l, a:r)++-- | Catches runtime (ie, IO) exceptions and inserts them into an 'Attempt'.+--+-- Like 'handle', the first argument to this function must explicitly state the+-- type of its input.+attemptIO :: (E.Exception eIn, E.Exception eOut)+          => (eIn -> eOut)+          -> IO v+          -> IO (Attempt v)+attemptIO f =+      E.handle (return . Failure . f)+    . fmap Success
LICENSE view
@@ -1,25 +1,25 @@-The following license covers this documentation, and the source code, except
-where otherwise indicated.
-
-Copyright 2008, Michael Snoyman. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
-OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+The following license covers this documentation, and the source code, except+where otherwise indicated.++Copyright 2008, Michael Snoyman. All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++* Redistributions of source code must retain the above copyright notice, this+  list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright notice,+  this list of conditions and the following disclaimer in the documentation+  and/or other materials provided with the distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Setup.lhs view
@@ -1,11 +1,11 @@-#!/usr/bin/env runhaskell
-
-> module Main where
-> import Distribution.Simple
-> import System.Cmd (system)
-
-> main :: IO ()
-> main = defaultMainWithHooks (simpleUserHooks { runTests = runTests' })
-
-> runTests' :: a -> b -> c -> d -> IO ()
-> runTests' _ _ _ _ = system "runhaskell Test.hs" >> return ()
+#!/usr/bin/env runhaskell++> module Main where+> import Distribution.Simple+> import System.Cmd (system)++> main :: IO ()+> main = defaultMainWithHooks (simpleUserHooks { runTests = runTests' })++> runTests' :: a -> b -> c -> d -> IO ()+> runTests' _ _ _ _ = system "runhaskell Test.hs" >> return ()
attempt.cabal view
@@ -1,19 +1,19 @@-name:            attempt
-version:         0.3.1.1
-license:         BSD3
-license-file:    LICENSE
-author:          Michael Snoyman, Nicolas Pouillard
-maintainer:      Michael Snoyman <michael@snoyman.com>
-synopsis:        Concrete data type for handling extensible exceptions as failures.
-description:     Defines a data type, Attempt, which has a Success and Failure constructor. Failure contains an extensible exception.
-category:        Data, Failure
-stability:       stable
-cabal-version:   >= 1.2
-build-type:      Simple
-homepage:        http://github.com/snoyberg/attempt/tree/master
-
-library
-    build-depends:   base >= 4 && < 5,
-                     failure >= 0.1.0 && < 0.2
-    exposed-modules: Data.Attempt
-    ghc-options:     -Wall
+name:            attempt+version:         0.4.0.1+license:         BSD3+license-file:    LICENSE+author:          Michael Snoyman, Nicolas Pouillard+maintainer:      Michael Snoyman <michael@snoyman.com>+synopsis:        Concrete data type for handling extensible exceptions as failures. (deprecated)+description:     Please use the exceptions package instead+category:        Data, Failure+stability:       stable+cabal-version:   >= 1.2+build-type:      Simple+homepage:        http://github.com/snoyberg/attempt/tree/master++library+    build-depends:   base >= 4 && < 5,+                     failure >= 0.2.0 && < 0.3+    exposed-modules: Data.Attempt+    ghc-options:     -Wall