unexceptionalio 0.1.0 → 0.2.0
raw patch · 3 files changed
+79/−18 lines, 3 filesdep −errorsdep −transformersdep ~basePVP ok
version bump matches the API change (PVP)
Dependencies removed: errors, transformers
Dependency ranges changed: base
API changes (from Hackage documentation)
+ UnexceptionalIO: syncIO :: IO a -> IO (Either SomeException a)
+ UnexceptionalIO: type UIO = UnexceptionalIO
- UnexceptionalIO: fromIO :: IO a -> EitherT SomeException UnexceptionalIO a
+ UnexceptionalIO: fromIO :: IO a -> UnexceptionalIO (Either SomeException a)
- UnexceptionalIO: fromIO' :: Exception e => IO a -> EitherT e UnexceptionalIO a
+ UnexceptionalIO: fromIO' :: Exception e => IO a -> UnexceptionalIO (Either e a)
- UnexceptionalIO: runEitherIO :: (MonadIO m, Exception e) => EitherT e UnexceptionalIO a -> m a
+ UnexceptionalIO: runEitherIO :: Exception e => UnexceptionalIO (Either e a) -> IO a
- UnexceptionalIO: runUnexceptionalIO :: MonadIO m => UnexceptionalIO a -> m a
+ UnexceptionalIO: runUnexceptionalIO :: UnexceptionalIO a -> IO a
Files
- COPYING +1/−1
- UnexceptionalIO.hs +70/−12
- unexceptionalio.cabal +8/−5
COPYING view
@@ -1,4 +1,4 @@-Copyright © 2011, Stephen Paul Weber <singpolyma.net>+Copyright © 2013, Stephen Paul Weber <singpolyma.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above
UnexceptionalIO.hs view
@@ -1,27 +1,51 @@+{-# LANGUAGE CPP #-} -- | When you've caught all the exceptions that can be handled safely, -- this is what you're left with. -- -- > runEitherIO . fromIO ≡ id module UnexceptionalIO ( UnexceptionalIO,+ UIO, fromIO, runUnexceptionalIO, runEitherIO, -- * Unsafe entry points+#ifdef __GLASGOW_HASKELL__ fromIO',- unsafeFromIO+#endif+ unsafeFromIO,+ -- * Utilities+ syncIO ) where import Control.Applicative (Applicative(..)) import Control.Monad (liftM, ap, (<=<)) import Control.Monad.Fix (MonadFix(..))-import Control.Error (syncIO, mapEitherT, EitherT(..), fmapLT)-import Control.Exception (SomeException, Exception, fromException, throwIO)-import Control.Monad.IO.Class (liftIO, MonadIO)+#ifdef __GLASGOW_HASKELL__+import Data.Dynamic (Dynamic)+import System.Exit (ExitCode)+import qualified Control.Exception as Ex +type SomeException = Ex.SomeException++throwIO :: (Ex.Exception e) => e -> IO a+throwIO = Ex.throwIO+#else+-- Haskell98 import 'IO' instead+import System.IO.Error (IOError, ioError, try)++type SomeException = IOError++throwIO :: SomeException -> IO a+throwIO = ioError+#endif+ -- | IO without any non-error, synchronous exceptions newtype UnexceptionalIO a = UnexceptionalIO (IO a) +-- | or, you may prefer a short name+type UIO = UnexceptionalIO+ instance Functor UnexceptionalIO where fmap = liftM @@ -39,27 +63,61 @@ mfix f = UnexceptionalIO (mfix $ runUnexceptionalIO . f) -- | Catch any non-error, synchronous exceptions in an 'IO' action-fromIO :: IO a -> EitherT SomeException UnexceptionalIO a-fromIO = mapEitherT unsafeFromIO . syncIO+fromIO :: IO a -> UnexceptionalIO (Either SomeException a)+fromIO = unsafeFromIO . syncIO -- | Re-embed 'UnexceptionalIO' into 'IO'-runUnexceptionalIO :: (MonadIO m) => UnexceptionalIO a -> m a-runUnexceptionalIO (UnexceptionalIO io) = liftIO io+runUnexceptionalIO :: UnexceptionalIO a -> IO a+runUnexceptionalIO (UnexceptionalIO io) = io -- | Re-embed 'UnexceptionalIO' and possible exception back into 'IO'-runEitherIO :: (MonadIO m, Exception e) => EitherT e UnexceptionalIO a -> m a-runEitherIO = either (liftIO . throwIO) return <=< runUnexceptionalIO . runEitherT+#ifdef __GLASGOW_HASKELL__+runEitherIO :: (Ex.Exception e) => UnexceptionalIO (Either e a) -> IO a+#else+runEitherIO :: UnexceptionalIO (Either SomeException a) -> IO a+#endif+runEitherIO = either throwIO return <=< runUnexceptionalIO +#ifdef __GLASGOW_HASKELL__ -- | You promise that 'e' covers all non-error, synchronous exceptions -- thrown by this 'IO' action -- -- This function is partial if you lie-fromIO' :: (Exception e) => IO a -> EitherT e UnexceptionalIO a-fromIO' = fmapLT (maybePartial . fromException) . fromIO+fromIO' :: (Ex.Exception e) => IO a -> UnexceptionalIO (Either e a)+fromIO' =+ (return . either (Left . maybePartial . Ex.fromException) Right) <=< fromIO where maybePartial (Just x) = x maybePartial Nothing = error "UnexceptionalIO.fromIO' exception of unspecified type"+#endif -- | You promise there are no exceptions thrown by this 'IO' action unsafeFromIO :: IO a -> UnexceptionalIO a unsafeFromIO = UnexceptionalIO++-- | Catch all exceptions, except for asynchronous exceptions found in @base@+syncIO :: IO a -> IO (Either SomeException a)+#ifdef __GLASGOW_HASKELL__+syncIO a = Ex.catches (fmap Right a) [+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.ArithException)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.ArrayException)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.AssertionFailed)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.AsyncException)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.BlockedIndefinitelyOnMVar)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.BlockedIndefinitelyOnSTM)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.Deadlock)),+ Ex.Handler (\e -> Ex.throwIO (e :: Dynamic)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.ErrorCall)),+ Ex.Handler (\e -> Ex.throwIO (e :: ExitCode)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.NestedAtomically)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.NoMethodError)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.NonTermination)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.PatternMatchFail)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.RecConError)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.RecSelError)),+ Ex.Handler (\e -> Ex.throwIO (e :: Ex.RecUpdError)),+ Ex.Handler (return . Left)+ ]+#else+syncIO = try+#endif
unexceptionalio.cabal view
@@ -1,9 +1,9 @@ name: unexceptionalio-version: 0.1.0+version: 0.2.0 cabal-version: >=1.8 license: OtherLicense license-file: COPYING-copyright: © 2013 Stephen Paul Weber+copyright: © 2013-2014 Stephen Paul Weber category: Control author: Stephen Paul Weber <singpolyma@singpolyma.net> maintainer: Stephen Paul Weber <singpolyma@singpolyma.net>@@ -15,15 +15,18 @@ description: When you've caught all the exceptions that can be handled safely, this is what you're left with.+ .+ It is intended that you use qualified imports with this library.+ .+ > import UnexceptionalIO (UIO)+ > import qualified UnexceptionalIO as UIO library exposed-modules: UnexceptionalIO build-depends:- base == 4.*,- errors >= 1.4.2,- transformers+ base == 4.* source-repository head type: git