packages feed

errors (empty) → 1.0.0

raw patch · 8 files changed

+469/−0 lines, 8 filesdep +EitherTdep +basedep +safesetup-changed

Dependencies added: EitherT, base, safe, transformers

Files

+ Control/Error.hs view
@@ -0,0 +1,31 @@+{-|+    Import this module in your code to access the entire library's+    functionality:++> import Control.Error++    This module exports the entire library as well as useful exports from other+    standard error-handling libraries.+-}++module Control.Error (+    module Control.Error.Script,+    module Control.Error.Safe,+    module Control.Error.Util,+    module Control.Monad.Trans.Either,+    module Control.Monad.Trans.Maybe,+    module Data.Either,+    module Data.EitherR,+    module Data.Maybe,+    module Safe+    ) where++import Control.Error.Script+import Control.Error.Safe+import Control.Error.Util+import Control.Monad.Trans.Either+import Control.Monad.Trans.Maybe+import Data.Either+import Data.EitherR+import Data.Maybe+import Safe
+ Control/Error/Safe.hs view
@@ -0,0 +1,141 @@+{-|+    This module extends the @safe@ library's functions with corresponding+    versions compatible with 'Either' and 'EitherT'.++    All functions take an exceptional value to return should they fail.++    I suffix the 'Either'-compatible functions with @Err@ and prefix the+    'EitherT'-compatible functions with @try@.++    Note that this library re-exports the 'Maybe' compatible functions from+    @safe@ in the "Control.Error" module, so they are not provided here.+-}++module Control.Error.Safe (+    -- * Either-compatible functions+    tailErr,+    initErr,+    headErr,+    lastErr,+    minimumErr,+    maximumErr,+    foldr1Err,+    foldl1Err,+    foldl1Err',+    atErr,+    readErr,+    assertErr,+    -- * EitherT-compatible functions+    tryTail,+    tryInit,+    tryHead,+    tryLast,+    tryMinimum,+    tryMaximum,+    tryFoldr1,+    tryFoldl1,+    tryFoldl1',+    tryAt,+    tryRead,+    tryAssert,+    ) where++import Control.Error.Util+import Control.Monad.Trans.Either+import Safe++-- | A 'tail' that fails in the 'Either' monad+tailErr :: e -> [a] -> Either e [a]+tailErr e = note e . tailMay++-- | An 'init' that fails in the 'Either' monad+initErr :: e -> [a] -> Either e [a]+initErr e = note e . initMay++-- | A 'head' that fails in the 'Either' monad+headErr :: e -> [a] -> Either e a+headErr e = note e . headMay++-- | A 'last' that fails in the 'Either' monad+lastErr :: e -> [a] -> Either e a+lastErr e = note e . lastMay++-- | A 'minimum' that fails in the 'Either' monad+minimumErr :: (Ord a) => e -> [a] -> Either e a+minimumErr e = note e . minimumMay++-- | A 'maximum' that fails in the 'Either' monad+maximumErr :: (Ord a) => e -> [a] -> Either e a+maximumErr e = note e . maximumMay++-- | A 'foldr1' that fails in the 'Either' monad+foldr1Err :: e -> (a -> a -> a) -> [a] -> Either e a+foldr1Err e step xs = note e $ foldr1May step xs++-- | A 'foldl1' that fails in the 'Either' monad+foldl1Err :: e -> (a -> a -> a) -> [a] -> Either e a+foldl1Err e step xs = note e $ foldl1May step xs++-- | A 'foldl1'' that fails in the 'Either' monad+foldl1Err' :: e -> (a -> a -> a) -> [a] -> Either e a+foldl1Err' e step xs = note e $ foldl1May' step xs++-- | A ('!!') that fails in the 'Either' monad+atErr :: e -> [a] -> Int -> Either e a+atErr e xs n = note e $ atMay xs n++-- | A 'read' that fails in the 'Either' monad+readErr :: (Read a) => e -> String -> Either e a+readErr e = note e . readMay++-- | An assertion that fails in the 'Either' monad+assertErr :: e -> Bool -> a -> Either e a+assertErr e p a = if p then Right a else Left e++-- | A 'tail' that fails in the 'EitherT' monad+tryTail :: (Monad m) => e -> [a] -> EitherT e m [a]+tryTail e xs = liftEither $ tailErr e xs++-- | An 'init' that fails in the 'EitherT' monad+tryInit :: (Monad m) => e -> [a] -> EitherT e m [a]+tryInit e xs = liftEither $ initErr e xs++-- | A 'head' that fails in the 'EitherT' monad+tryHead :: (Monad m) => e -> [a] -> EitherT e m a+tryHead e xs = liftEither $ headErr e xs++-- | A 'last' that fails in the 'EitherT' monad+tryLast :: (Monad m) => e -> [a] -> EitherT e m a+tryLast e xs = liftEither $ lastErr e xs++-- | A 'minimum' that fails in the 'EitherT' monad+tryMinimum :: (Monad m, Ord a) => e -> [a] -> EitherT e m a+tryMinimum e xs = liftEither $ maximumErr e xs++-- | A 'maximum' that fails in the 'EitherT' monad+tryMaximum :: (Monad m, Ord a) => e -> [a] -> EitherT e m a+tryMaximum e xs = liftEither $ maximumErr e xs++-- | A 'foldr1' that fails in the 'EitherT' monad+tryFoldr1 :: (Monad m) => e -> (a -> a -> a) -> [a] -> EitherT e m a+tryFoldr1 e step xs = liftEither $ foldr1Err e step xs++-- | A 'foldl1' that fails in the 'EitherT' monad+tryFoldl1 :: (Monad m) => e -> (a -> a -> a) -> [a] -> EitherT e m a+tryFoldl1 e step xs = liftEither $ foldl1Err e step xs++-- | A 'foldl1'' that fails in the 'EitherT' monad+tryFoldl1' :: (Monad m) => e -> (a -> a -> a) -> [a] -> EitherT e m a+tryFoldl1' e step xs = liftEither $ foldl1Err' e step xs++-- | A ('!!') that fails in the 'EitherT' monad+tryAt :: (Monad m) => e -> [a] -> Int -> EitherT e m a+tryAt e xs n = liftEither $ atErr e xs n++-- | A 'read' that fails in the 'EitherT' monad+tryRead :: (Monad m, Read a) => e -> String -> EitherT e m a+tryRead e str = liftEither $ readErr e str++-- | An assertion that fails in the 'EitherT' monad+tryAssert :: (Monad m) => e -> Bool -> a -> EitherT e m a+tryAssert e p a = liftEither $ assertErr e p a
+ Control/Error/Script.hs view
@@ -0,0 +1,57 @@+{-|+    Use this module if you like to write simple scripts, but you prefer to use+    'EitherT' to handle errors rather than @Control.Exception@.++> import Control.Error+>+> main = runScript $ do+>     str <- tryIO getLine+>     n   <- tryRead "Read failed" str+>     tryIO $ print (n + 1)+-}++module Control.Error.Script (+    -- * The Script Monad+    Script,+    runScript,+    tryMaybe,+    tryEither,+    tryIO+    ) where++import Control.Exception+import Control.Monad.Trans.Either+import Control.Error.Util+import Data.EitherR+import System.IO+import System.Exit++-- | An 'IO' action that can fail with a 'String' error message+type Script = EitherT String IO++{-|+    Runs the 'Script' monad++    Prints the first error to 'stderr' and exits with 'exitFailure'+-}+runScript :: Script a -> IO a+runScript s = do+    e <- runEitherT s+    case e of+        Left  e -> do+            hPutStrLn stderr e+            exitFailure+        Right a -> return a++-- | A 'Maybe' that fails in the 'Script' monad+tryMaybe :: String -> Maybe a -> Script a+tryMaybe str = tryEither . note str++-- | An 'Either' that fails in the 'Script' monad+tryEither :: Either String r -> Script r+tryEither = liftEither++-- | 'tryIO' is like 'lift', except it converts exceptions to the 'Script' monad+tryIO :: IO a -> Script a+tryIO io = EitherT . fmap (fmapL show)+                   $ (try :: IO a -> IO (Either SomeException a)) io
+ Control/Error/Util.hs view
@@ -0,0 +1,38 @@+{-|+    Use this module to convert between 'Maybe', 'Either', 'MaybeT', and+    'EitherT'.+-}++module Control.Error.Util where++import Control.Monad+import Control.Monad.Trans.Either+import Control.Monad.Trans.Maybe++-- | Suppress the 'Left' value of an 'Either'+hush :: Either a b -> Maybe b+hush e = case e of+    Left  _ -> Nothing+    Right b -> Just b++-- | Suppress the 'Left' value of an 'EitherT'+hushT :: (Monad m) => EitherT a m b -> MaybeT m b+hushT = MaybeT . liftM hush . runEitherT++-- | Tag the 'Nothing' value of a 'Maybe'+note :: a -> Maybe b -> Either a b+note a m = case m of+    Nothing -> Left  a+    Just b  -> Right b++-- | Tag the 'Nothing' value of a 'MaybeT'+noteT :: (Monad m) => a -> MaybeT m b -> EitherT a m b+noteT a = EitherT . liftM (note a) . runMaybeT++-- | Lift a 'Maybe' to the 'MaybeT' monad+liftMaybe :: (Monad m) => Maybe b -> MaybeT m b+liftMaybe = MaybeT . return++-- | Lift an 'Either' to the 'EitherT' monad+liftEither :: (Monad m) => Either a b -> EitherT a m b+liftEither = EitherT . return
+ Data/EitherR.hs view
@@ -0,0 +1,142 @@+{-|+    This modules provides newtypes which flip the type variables of 'Either'+    and 'EitherT' to access the symmetric monad over the opposite type variable.++    This module provides the following simple benefits to the casual user:++    * A type-class free alternative to @MonadError@++    * No @UndecidableInstances@ or any other extensions, for that matter++    * A more powerful 'catchE' statement that allows you to change the type of+      error value returned++    More advanced users can take advantage of the fact that 'EitherR' and+    'EitherRT' define an entirely symmetric \"success monad\" where+    error-handling computations are the default and successful results terminate+    the monad.  This allows you to chain error-handlers and pass around values+    other than exceptions until you can finally recover from the error:++> runEitherRT $ do+>     e2 <- ioExceptionHandler e1+>     bool <- arithmeticExceptionhandler e2+>     when bool $ lift $ putStrLn "DEBUG: Arithmetic handler did something"++    If any of the above error handlers 'succeed', no other handlers are tried.+-}++module Data.EitherR (+    EitherR(..),+    -- ** Operations in the EitherR monad+    succeed,+    -- ** Conversions to the Either monad+    throwE,+    catchE,+    handleE,+    fmapL,+    -- * EitherRT+    EitherRT(..),+    -- ** Operations in the EitherRT monad+    right,+    succeedT,+    -- ** Conversions to the EitherT monad+    throwT,+    catchT,+    handleT,+    fmapLT+    ) where++import Control.Applicative+import Control.Monad+import Control.Monad.Trans.Class+import Control.Monad.Trans.Either++{-|+    If \"@Either e r@\" is the error monad, then \"@EitherR r e@\" is the+    corresponding success monad, where:++    * 'return' is 'throwE'.++    * ('>>=') is 'catchE'.++    * Successful results abort the computation+-}+newtype EitherR r e = EitherR { runEitherR :: Either e r }++instance Functor (EitherR r) where+    fmap = liftM++instance Applicative (EitherR r) where+    pure  = return+    (<*>) = ap++instance Monad (EitherR r) where+    return = EitherR . Left+    (EitherR m) >>= f = EitherR $ case m of+        Left  e -> runEitherR (f e)+        Right r -> Right r++-- | Complete error handling, returning a result+succeed :: r -> EitherR r e+succeed = EitherR . return++-- | 'throwE' in the error monad corresponds to 'return' in the success monad+throwE :: e -> Either e r+throwE = runEitherR . return++-- | 'catchE' in the error monad corresponds to ('>>=') in the success monad+catchE :: Either a r -> (a -> Either b r) -> Either b r+e `catchE` f = runEitherR $ (EitherR e) >>= (EitherR . f)++-- | 'catchE' with the arguments flipped+handleE :: (a -> Either b r) -> Either a r -> Either b r+handleE = flip catchE++-- | Map a function over the 'Left' value of an 'Either'+fmapL :: (a -> b) -> Either a r -> Either b r+fmapL f = runEitherR . fmap f . EitherR++-- | 'EitherR' converted into a monad transformer+newtype EitherRT r m e = EitherRT { runEitherRT :: EitherT e m r }++instance (Monad m) => Functor (EitherRT r m) where+    fmap = liftM++instance (Monad m) => Applicative (EitherRT r m) where+    pure  = return+    (<*>) = ap++instance (Monad m) => Monad (EitherRT r m) where+    return = EitherRT . left+    m >>= f = EitherRT $ EitherT $ do+        x <- runEitherT $ runEitherRT m+        runEitherT $ runEitherRT $ case x of+            Left  e -> f e+            Right r -> right r++instance MonadTrans (EitherRT r) where+    lift = EitherRT . EitherT . liftM Left++-- | The dual to 'left' and synonymous with 'succeedT'+right :: (Monad m) => r -> EitherRT r m e+right = EitherRT . return++-- | Complete error handling, returning a result+succeedT :: (Monad m) => r -> EitherRT r m e+succeedT = right++-- | 'throwT' in the error monad corresponds to 'return' in the success monad+throwT :: (Monad m) => e -> EitherT e m r+throwT = runEitherRT . return++-- | 'catchT' in the error monad corresponds to ('>>=') in the success monad+catchT :: (Monad m) => EitherT a m r -> (a -> EitherT b m r) -> EitherT b m r+e `catchT` f = runEitherRT $ (EitherRT e) >>= (EitherRT . f)++-- | 'catchT' with the arguments flipped+handleT :: (Monad m) => (a -> EitherT b m r) -> EitherT a m r -> EitherT b m r+handleT = flip catchT++-- | Map a function over the 'Left' value of an 'EitherT'+fmapLT :: (Monad m) => (a -> b) -> EitherT a m r -> EitherT b m r+fmapLT f = runEitherRT . fmap f . EitherRT
+ LICENSE view
@@ -0,0 +1,24 @@+Copyright (c) 2012, Gabriel Gonzalez+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.+    * Neither the name of Gabriel Gonzalez nor the names of other contributors+      may be used to endorse or promote products derived from this software+      without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 OWNER OR CONTRIBUTORS 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.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ errors.cabal view
@@ -0,0 +1,34 @@+Name: errors+Version: 1.0.0+Cabal-Version: >=1.14.0+Build-Type: Simple+License: BSD3+License-File: LICENSE+Copyright: 2012 Gabriel Gonzalez+Author: Gabriel Gonzalez+Maintainer: Gabriel439@gmail.com+Stability: Experimental+Bug-Reports: https://github.com/Gabriel439/Haskell-Errors-Library/issues+Synopsis: Simplified error-handling+Description:+    The one-stop shop for all your error-handling needs!  Just import+    "Control.Error".+    .+    This library encourages an error-handling style that directly uses the type+    system, rather than out-of-band exceptions.+Category: Control, Error Handling+Tested-With: GHC ==7.4.1+Source-Repository head+    Type: git+    Location: https://github.com/Gabriel439/Haskell-Errors-Library++Library+    Build-Depends: base >= 4 && < 5, EitherT, safe, transformers+    Exposed-Modules:+        Control.Error,+        Control.Error.Script,+        Control.Error.Util,+        Control.Error.Safe,+        Data.EitherR+    GHC-Options: -O2+    Default-Language: Haskell2010