errors 1.3.1 → 1.4.0
raw patch · 6 files changed
+192/−97 lines, 6 filesdep ~basedep ~eitherdep ~safePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, either, safe, transformers
API changes (from Hackage documentation)
+ Control.Error.Util: just :: Monad m => a -> MaybeT m a
+ Control.Error.Util: maybeT :: Monad m => m b -> (a -> m b) -> MaybeT m a -> m b
+ Control.Error.Util: nothing :: Monad m => MaybeT m a
+ Data.EitherR: instance (Monad m, Monoid r) => Alternative (EitherRT r m)
+ Data.EitherR: instance (Monad m, Monoid r) => MonadPlus (EitherRT r m)
+ Data.EitherR: instance MonadIO m => MonadIO (EitherRT r m)
+ Data.EitherR: instance Monoid r => Alternative (EitherR r)
+ Data.EitherR: instance Monoid r => MonadPlus (EitherR r)
- Control.Error.Util: fmapRT :: Functor m => (a -> b) -> EitherT l m a -> EitherT l m b
+ Control.Error.Util: fmapRT :: Monad m => (a -> b) -> EitherT l m a -> EitherT l m b
Files
- Control/Error.hs +63/−25
- Control/Error/Safe.hs +35/−28
- Control/Error/Util.hs +25/−5
- Data/EitherR.hs +63/−32
- LICENSE +1/−1
- errors.cabal +5/−6
Control/Error.hs view
@@ -5,8 +5,30 @@ > import Control.Error This module exports the entire library as well as useful exports from other- standard error-handling libraries.+ standard error-handling libraries: + * "Control.Error.Safe": Generalizes the @safe@ library, including 'Either',+ 'EitherT', and 'MonadPlus' variations on total functions++ * "Control.Error.Script": Support for simple scripts that catch all errors+ and transform them to 'String's++ * "Control.Error.Util": Utility functions and conversions between common+ error-handling types++ * @Control.Monad.Trans.Either@: The 'EitherT' monad transformer++ * @Control.Monad.Trans.Maybe@: The 'MaybeT' monad transformer++ * @Data.Either@: 'Either' utility functions++ * "Data.EitherR": throw and catch functions, and their corresponding+ \"success\" monads++ * @Data.Maybe@: 'Maybe' utility functions++ * @Safe@: Total versions of partial Prelude functions+ This module does not re-export partial functions from other libraries. -} @@ -25,28 +47,44 @@ import Control.Error.Safe import Control.Error.Script import Control.Error.Util-import Control.Monad.Trans.Either-import Control.Monad.Trans.Maybe-import Data.Either+import Control.Monad.Trans.Either (+ eitherT, bimapEitherT, mapEitherT, hoistEither, left, right )+import Control.Monad.Trans.Maybe (+ mapMaybeT, liftCallCC, liftCatch, liftListen, liftPass )+import Data.Either (either, lefts, rights, partitionEithers) import Data.EitherR-import Data.Maybe hiding (fromJust)-import Safe hiding (- tailNote,- initNote,- headNote,- lastNote,- minimumNote,- maximumNote,- foldr1Note,- foldl1Note,- foldl1Note',- fromJustNote,- assertNote,- at,- atNote,- readNote,- lookupJust,- lookupJustNote,- findJust,- findJustNote,- abort)+import Data.Maybe (+ maybe,+ isJust,+ isNothing,+ fromMaybe,+ listToMaybe,+ maybeToList,+ catMaybes,+ mapMaybe )+import Safe (+ tailDef,+ tailMay,+ tailSafe,+ initDef,+ initMay,+ initSafe,+ headDef,+ headMay,+ lastDef,+ lastMay,+ minimumDef,+ minimumMay,+ maximumDef,+ maximumMay,+ foldr1Def,+ foldr1May,+ foldl1Def',+ foldl1May',+ fromJustDef,+ atDef,+ atMay,+ readDef,+ readMay,+ lookupJustDef,+ findJustDef )
Control/Error/Safe.hs view
@@ -1,15 +1,22 @@ {-| This module extends the @safe@ library's functions with corresponding- versions compatible with 'Either' and 'EitherT', and also provides several+ versions compatible with 'Either' and 'EitherT', and also provides a few 'Maybe'-compatible functions missing from @safe@. - 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.++ The \'@Z@\'-suffixed functions generalize the 'Maybe' functions to also work+ with anything that implements 'MonadPlus', including:++ * Lists++ * Most parsers++ * 'EitherT' (if the left value is a 'Monoid') -} module Control.Error.Safe (@@ -65,7 +72,7 @@ import Control.Error.Util (note) import Control.Monad (MonadPlus(mzero)) import Control.Monad.Trans.Either (EitherT, hoistEither)-import Safe+import qualified Safe as S -- | An assertion that fails in the 'Maybe' monad assertMay :: Bool -> Maybe ()@@ -73,51 +80,51 @@ -- | A 'fromRight' that fails in the 'Maybe' monad rightMay :: Either e a -> Maybe a-rightMay = either (\_ -> Nothing) Just+rightMay = rightZ -- | A 'tail' that fails in the 'Either' monad tailErr :: e -> [a] -> Either e [a]-tailErr e = note e . tailMay+tailErr e = note e . S.tailMay -- | An 'init' that fails in the 'Either' monad initErr :: e -> [a] -> Either e [a]-initErr e = note e . initMay+initErr e = note e . S.initMay -- | A 'head' that fails in the 'Either' monad headErr :: e -> [a] -> Either e a-headErr e = note e . headMay+headErr e = note e . S.headMay -- | A 'last' that fails in the 'Either' monad lastErr :: e -> [a] -> Either e a-lastErr e = note e . lastMay+lastErr e = note e . S.lastMay -- | A 'minimum' that fails in the 'Either' monad minimumErr :: (Ord a) => e -> [a] -> Either e a-minimumErr e = note e . minimumMay+minimumErr e = note e . S.minimumMay -- | A 'maximum' that fails in the 'Either' monad maximumErr :: (Ord a) => e -> [a] -> Either e a-maximumErr e = note e . maximumMay+maximumErr e = note e . S.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+foldr1Err e step xs = note e $ S.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+foldl1Err e step xs = note e $ S.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+foldl1Err' e step xs = note e $ S.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+atErr e xs n = note e $ S.atMay xs n -- | A 'read' that fails in the 'Either' monad readErr :: (Read a) => e -> String -> Either e a-readErr e = note e . readMay+readErr e = note e . S.readMay -- | An assertion that fails in the 'Either' monad assertErr :: e -> Bool -> Either e ()@@ -185,47 +192,47 @@ -- | A 'tail' that fails using 'mzero' tailZ :: (MonadPlus m) => [a] -> m [a]-tailZ = maybe mzero return . tailMay+tailZ = maybe mzero return . S.tailMay -- | An 'init' that fails using 'mzero' initZ :: (MonadPlus m) => [a] -> m [a]-initZ = maybe mzero return . initMay+initZ = maybe mzero return . S.initMay -- | A 'head' that fails using 'mzero' headZ :: (MonadPlus m) => [a] -> m a-headZ = maybe mzero return . headMay+headZ = maybe mzero return . S.headMay -- | A 'last' that fails using 'mzero' lastZ :: (MonadPlus m) => [a] -> m a-lastZ = maybe mzero return . lastMay+lastZ = maybe mzero return . S.lastMay -- | A 'minimum' that fails using 'mzero' minimumZ :: (MonadPlus m) => (Ord a) => [a] -> m a-minimumZ = maybe mzero return . minimumMay+minimumZ = maybe mzero return . S.minimumMay -- | A 'maximum' that fails using 'mzero' maximumZ :: (MonadPlus m) => (Ord a) => [a] -> m a-maximumZ = maybe mzero return . maximumMay+maximumZ = maybe mzero return . S.maximumMay -- | A 'foldr1' that fails using 'mzero' foldr1Z :: (MonadPlus m) => (a -> a -> a) -> [a] -> m a-foldr1Z step xs = maybe mzero return $ foldr1May step xs+foldr1Z step xs = maybe mzero return $ S.foldr1May step xs -- | A 'foldl1' that fails using 'mzero' foldl1Z :: (MonadPlus m) => (a -> a -> a) -> [a] -> m a-foldl1Z step xs = maybe mzero return $ foldl1May step xs+foldl1Z step xs = maybe mzero return $ S.foldl1May step xs -- | A 'foldl1'' that fails using 'mzero' foldl1Z' :: (MonadPlus m) => (a -> a -> a) -> [a] -> m a-foldl1Z' step xs = maybe mzero return $ foldl1May' step xs+foldl1Z' step xs = maybe mzero return $ S.foldl1May' step xs -- | A ('!!') that fails using 'mzero' atZ :: (MonadPlus m) => [a] -> Int -> m a-atZ xs n = maybe mzero return $ atMay xs n+atZ xs n = maybe mzero return $ S.atMay xs n -- | A 'read' that fails using 'mzero' readZ :: (MonadPlus m) => (Read a) => String -> m a-readZ = maybe mzero return . readMay+readZ = maybe mzero return . S.readMay -- | An assertion that fails using 'mzero' assertZ :: (MonadPlus m) => Bool -> m ()@@ -237,4 +244,4 @@ -- | A 'fromRight' that fails using 'mzero' rightZ :: (MonadPlus m) => Either e a -> m a-rightZ = either (\_ -> mzero) return+rightZ = either (const mzero) return
Control/Error/Util.hs view
@@ -8,6 +8,10 @@ note, noteT, hoistMaybe,+ -- * MaybeT+ maybeT,+ just,+ nothing, -- * Either isLeft, isRight,@@ -39,7 +43,7 @@ -} -- | Suppress the 'Left' value of an 'Either' hush :: Either a b -> Maybe b-hush = either (\_ -> Nothing) Just+hush = either (const Nothing) Just -- | Suppress the 'Left' value of an 'EitherT' hushT :: (Monad m) => EitherT a m b -> MaybeT m b@@ -57,21 +61,37 @@ hoistMaybe :: (Monad m) => Maybe b -> MaybeT m b hoistMaybe = MaybeT . return +{-| Case analysis for 'MaybeT'++ Use the first argument if the 'MaybeT' computation fails, otherwise apply+ the function to the successful result.+-}+maybeT :: Monad m => m b -> (a -> m b) -> MaybeT m a -> m b+maybeT mb kb (MaybeT ma) = ma >>= maybe mb kb++-- | Analogous to 'Just' and equivalent to 'return'+just :: (Monad m) => a -> MaybeT m a+just a = MaybeT (return (Just a))++-- | Analogous to 'Nothing' and equivalent to 'mzero'+nothing :: (Monad m) => MaybeT m a+nothing = MaybeT (return Nothing)+ -- | Returns whether argument is a 'Left' isLeft :: Either a b -> Bool-isLeft = either (\_ -> True) (\_ -> False)+isLeft = either (const True) (const False) -- | Returns whether argument is a 'Right' isRight :: Either a b -> Bool-isRight = either (\_ -> False) (\_ -> True)+isRight = either (const False) (const True) -- | 'fmap' specialized to 'Either', given a name symmetric to 'fmapL' fmapR :: (a -> b) -> Either l a -> Either l b fmapR = fmap -- | 'fmap' specialized to 'EitherT', given a name symmetric to 'fmapLT'-fmapRT :: (Functor m) => (a -> b) -> EitherT l m a -> EitherT l m b-fmapRT = fmap+fmapRT :: (Monad m) => (a -> b) -> EitherT l m a -> EitherT l m b+fmapRT = liftM -- | Write a string to standard error err :: String -> IO ()
Data/EitherR.hs view
@@ -1,24 +1,24 @@ {-|- 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:+ This module provides 'throwE' and 'catchE' for 'Either'. These two+ functions reside here because 'throwE' and 'catchE' correspond to 'return'+ and ('>>=') for the flipped 'Either' monad: 'EitherR'. Similarly, this+ module defines 'throwT' and 'catchT' for 'EitherT', which correspond to the+ 'Monad' operations for 'EitherRT'. - * A type-class free alternative to @MonadError@+ These throw and catch functions improve upon @MonadError@ because: - * No @UndecidableInstances@ or any other extensions, for that matter+ * 'catch' is more general and allows you to change the left value's type - * A more powerful 'catchE' statement that allows you to change the type of- error value returned+ * They are Haskell98 - 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:+ More advanced users can use 'EitherR' and 'EitherRT' to program in an+ entirely symmetric \"success monad\" where exceptional results are the norm+ and successful results terminate the computation. This allows you to chain+ error-handlers using @do@ notation and pass around exceptional values of+ varying types until you can finally recover from the error: > runEitherRT $ do-> e2 <- ioExceptionHandler e1+> e2 <- ioExceptionHandler e1 > bool <- arithmeticExceptionhandler e2 > when bool $ lift $ putStrLn "DEBUG: Arithmetic handler did something" @@ -54,13 +54,14 @@ flipET, ) where -import Control.Applicative-import Control.Monad-import Control.Monad.Trans.Class-import Control.Monad.Trans.Either+import Control.Applicative (Applicative(pure, (<*>)), Alternative(empty, (<|>)))+import Control.Monad (liftM, ap, MonadPlus(mzero, mplus))+import Control.Monad.Trans.Class (MonadTrans(lift))+import Control.Monad.IO.Class (MonadIO(liftIO))+import Control.Monad.Trans.Either (EitherT(EitherT, runEitherT), left, right)+import Data.Monoid (Monoid(mempty, mappend)) -{-|- If \"@Either e r@\" is the error monad, then \"@EitherR r e@\" is the+{-| If \"@Either e r@\" is the error monad, then \"@EitherR r e@\" is the corresponding success monad, where: * 'return' is 'throwE'.@@ -79,22 +80,33 @@ (<*>) = 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+ return e = EitherR (Left e)+ EitherR m >>= f = case m of+ Left e -> f e+ Right r -> EitherR (Right r) +instance (Monoid r) => Alternative (EitherR r) where+ empty = EitherR (Right mempty)+ e1@(EitherR (Left _)) <|> _ = e1+ _ <|> e2@(EitherR (Left _)) = e2+ EitherR (Right r1) <|> EitherR (Right r2)+ = EitherR (Right (mappend r1 r2))++instance (Monoid r) => MonadPlus (EitherR r) where+ mzero = empty+ mplus = (<|>)+ -- | Complete error handling, returning a result succeed :: r -> EitherR r e-succeed = EitherR . return+succeed r = EitherR (return r) -- | 'throwE' in the error monad corresponds to 'return' in the success monad throwE :: e -> Either e r-throwE = runEitherR . return+throwE e = runEitherR (return e) -- | '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)+e `catchE` f = runEitherR $ EitherR e >>= \a -> EitherR (f a) -- | 'catchE' with the arguments flipped handleE :: (a -> Either b r) -> Either a r -> Either b r@@ -121,27 +133,46 @@ (<*>) = ap instance (Monad m) => Monad (EitherRT r m) where- return = EitherRT . left+ return e = EitherRT (left e) m >>= f = EitherRT $ EitherT $ do x <- runEitherT $ runEitherRT m runEitherT $ runEitherRT $ case x of Left e -> f e- Right r -> succeedT r+ Right r -> EitherRT (right r) +instance (Monad m, Monoid r) => Alternative (EitherRT r m) where+ empty = EitherRT $ EitherT $ return $ Right mempty+ e1 <|> e2 = EitherRT $ EitherT $ do+ x1 <- runEitherT $ runEitherRT e1+ case x1 of+ Left l -> return (Left l)+ Right r1 -> do+ x2 <- runEitherT $ runEitherRT e2+ case x2 of+ Left l -> return (Left l)+ Right r2 -> return (Right (mappend r1 r2))++instance (Monad m, Monoid r) => MonadPlus (EitherRT r m) where+ mzero = empty+ mplus = (<|>)+ instance MonadTrans (EitherRT r) where lift = EitherRT . EitherT . liftM Left +instance (MonadIO m) => MonadIO (EitherRT r m) where+ liftIO = lift . liftIO+ -- | Complete error handling, returning a result succeedT :: (Monad m) => r -> EitherRT r m e-succeedT = EitherRT . return+succeedT r = EitherRT (return r) -- | 'throwT' in the error monad corresponds to 'return' in the success monad throwT :: (Monad m) => e -> EitherT e m r-throwT = runEitherRT . return+throwT e = runEitherRT (return e) -- | '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)+e `catchT` f = runEitherRT $ EitherRT e >>= \a -> EitherRT (f a) -- | 'catchT' with the arguments flipped handleT :: (Monad m) => (a -> EitherT b m r) -> EitherT a m r -> EitherT b m r
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2012, Gabriel Gonzalez+Copyright (c) 2012, 2013, Gabriel Gonzalez All rights reserved. Redistribution and use in source and binary forms, with or without modification,
errors.cabal view
@@ -1,13 +1,12 @@ Name: errors-Version: 1.3.1+Version: 1.4.0 Cabal-Version: >=1.8.0.2 Build-Type: Simple License: BSD3 License-File: LICENSE-Copyright: 2012 Gabriel Gonzalez+Copyright: 2012, 2013 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:@@ -25,9 +24,9 @@ Library Build-Depends: base >= 4 && < 5,- either >= 3.0.1,- safe >= 0.3.3,- transformers >= 0.2+ either >= 3.1 && < 3.5,+ safe >= 0.3.3 && < 0.4,+ transformers >= 0.2 && < 0.4 Exposed-Modules: Control.Error, Control.Error.Safe,