failable 0.1.0.3 → 0.1.1.0
raw patch · 2 files changed
+32/−5 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Control.Monad.Failable: failableIO :: (Failable m, MonadIO m) => IO a -> m a
Files
- failable.cabal +2/−2
- src/Control/Monad/Failable.hs +30/−3
failable.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: bf2c314c1ef35bb95db8c0f1d14aa05f8b2da20a6e76dace01662f21847ee451+-- hash: b01d6b6dff5f662173986cc7e39625f19f05b65bebdc8744818c97741cfd6c90 name: failable-version: 0.1.0.3+version: 0.1.1.0 synopsis: A 'Failable' error monad class to unify failure across monads that can fail description: Please see the README on Gitlab at <https://gitlab.com/codemonkeylabs/failable#readme> category: control, exceptions, monad
src/Control/Monad/Failable.hs view
@@ -49,7 +49,7 @@ -- is to provide the underlying monad (transformer) with `Maybe` like behaviour, i.e. have -- @Nothing@ be returned in case of aborting the 'Maybe' pipeline so to speak, then throwing an -- exception defeats IMHO the purpose of using 'MaybeT' in the first place.--- +-- -- >>> foo 2 :: Maybe Int -- >>> Nothing --@@ -61,12 +61,14 @@ -- -- >>> runMaybeT $ foo 2 :: IO (Maybe Int) -- >>> Nothing--- - Failable(..)) where+--+ Failable(..), failableIO) where import Control.Exception (Exception(..), SomeException, throw) import Control.Monad.Except (ExceptT, throwError)+import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Trans.Maybe (MaybeT(..))+import System.IO.Error (tryIOError) -- | The 'Failable' class. A Monad which is an instance of this class can be used as a context@@ -95,3 +97,28 @@ instance (Monad m, e ~ SomeException) => Failable (ExceptT e m) where failure = throwError . toException +-- | Perform a set of IO actions in a 'Failable' 'MonadIO' instance, triggering a+-- 'failure' upon an IO exception, instead of blindly triggering an asynchronos exception. This+-- serves ultimately to unify error handling in the 'Failable' context. For example:+--+-- @+-- foo :: (Failable m, MonadIO m) => m ()+-- foo = do+-- failableIO $ do+-- txt <- readFile "foo.txt"+-- putStrLn txt+-- @+--+-- >>> λ> runExceptT foo+-- >>> Left foo.txt: openFile: does not exist (No such file or directory)+-- >>>+-- >>> λ> runMaybeT foo+-- >>> Nothing+-- >>>+-- >>> λ> foo+-- >>> *** Exception: foo.txt: openFile: does not exist (No such file or directory)+--+failableIO :: (Failable m, MonadIO m) => IO a -> m a+failableIO actions = do+ result <- liftIO . tryIOError $ actions+ either failure return result