-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Exceptions which are explicit in the type signature.
--
-- Synchronous and Asynchronous exceptions which are explicit in the type
-- signature. The first ones are very similar to Either and
-- Control.Monad.Error.ErrorT. The second ones are used for
-- System.IO.readFile and System.IO.hGetContents. This
-- package is a proposal for improved exception handling in Haskell. It
-- strictly separates between handling of exceptional situations (file
-- not found, invalid user input, see
-- http://www.haskell.org/haskellwiki/Exception) and (programming)
-- errors (division by zero, index out of range, see
-- http://www.haskell.org/haskellwiki/Error). Handling of the
-- first one is called "exception handling", whereas handling of errors
-- is better known as "debugging".
--
-- For an application see the midi package.
--
-- Although I'm not happy with the identifier style of the Monad Template
-- Library (partially intended for unqualified use) I have tried to adopt
-- it for this library, in order to let Haskell programmers get
-- accustomed easily to it.
--
-- To do: Because many people requested it, we will provide a
-- bracket function that frees a resource both when an exception
-- and an error occurs, that is, it combines exception handling and
-- debugging. However note that freeing resources in case of an error is
-- dangerous and may cause further damage.
@package explicit-exception
@version 0.1
-- | Synchronous exceptions immediately abort a series of computations. We
-- provide monads for describing this behaviour.
module Control.Monad.Exception.Synchronous
-- | Like Either, but explicitly intended for handling of
-- exceptional results. In contrast to Either we do not support
-- fail. Calling fail in the Exceptional monad is an
-- error. This way, we do not require that an exception can be derived
-- from a String, yet, we require no constraint on the exception
-- type at all.
data Exceptional e a
Success :: a -> Exceptional e a
Exception :: e -> Exceptional e a
fromMaybe :: e -> Maybe a -> Exceptional e a
fromEither :: Either e a -> Exceptional e a
toEither :: Exceptional e a -> Either e a
-- | useful in connection with
-- Control.Monad.Exception.Asynchronous.continue
getExceptionNull :: Exceptional e () -> Maybe e
-- | If you are sure that the value is always a Success you can tell
-- that the run-time system thus making your program lazy. However, try
-- to avoid this function by using catch and friends, since this
-- function is partial.
force :: Exceptional e a -> Exceptional e a
mapException :: (e0 -> e1) -> Exceptional e0 a -> Exceptional e1 a
mapExceptional :: (e0 -> e1) -> (a -> b) -> Exceptional e0 a -> Exceptional e1 b
throw :: e -> Exceptional e a
catch :: Exceptional e0 a -> (e0 -> Exceptional e1 a) -> Exceptional e1 a
resolve :: (e -> a) -> Exceptional e a -> a
-- | like ErrorT, but ExceptionalT is the better name in order to
-- distinguish from real (programming) errors
newtype ExceptionalT e m a
ExceptionalT :: m (Exceptional e a) -> ExceptionalT e m a
runExceptionalT :: ExceptionalT e m a -> m (Exceptional e a)
fromErrorT :: (Monad m) => ErrorT e m a -> ExceptionalT e m a
toErrorT :: (Monad m) => ExceptionalT e m a -> ErrorT e m a
fromEitherT :: (Monad m) => m (Either e a) -> ExceptionalT e m a
toEitherT :: (Monad m) => ExceptionalT e m a -> m (Either e a)
-- | see force
forceT :: (Monad m) => ExceptionalT e m a -> ExceptionalT e m a
mapExceptionT :: (Monad m) => (e0 -> e1) -> ExceptionalT e0 m a -> ExceptionalT e1 m a
mapExceptionalT :: (m (Exceptional e0 a) -> n (Exceptional e1 b)) -> ExceptionalT e0 m a -> ExceptionalT e1 n b
throwT :: (Monad m) => e -> ExceptionalT e m a
catchT :: (Monad m) => ExceptionalT e0 m a -> (e0 -> ExceptionalT e1 m a) -> ExceptionalT e1 m a
-- | If the enclosed monad has custom exception facilities, they could skip
-- the cleanup code. Make sure, that this cannot happen by choosing an
-- appropriate monad.
bracketT :: (Monad m) => ExceptionalT e m h -> (h -> ExceptionalT e m ()) -> (h -> ExceptionalT e m a) -> ExceptionalT e m a
resolveT :: (Monad m) => (e -> m a) -> ExceptionalT e m a -> m a
tryT :: (Monad m) => ExceptionalT e m a -> m (Exceptional e a)
-- | Repeat an action until an exception occurs. Initialize the result with
-- empty and add new elements using cons (e.g.
-- [] and (:)). The exception handler decides whether
-- the terminating exception is re-raised (Just) or catched
-- (Nothing).
manyT :: (Monad m) => (e0 -> Maybe e1) -> (a -> b -> b) -> b -> ExceptionalT e0 m a -> ExceptionalT e1 m b
instance (Show e, Show a) => Show (Exceptional e a)
instance (Eq e, Eq a) => Eq (Exceptional e a)
instance MonadTrans (ExceptionalT e)
instance (MonadFix m) => MonadFix (ExceptionalT e m)
instance (Monad m) => Monad (ExceptionalT e m)
instance (Applicative m) => Applicative (ExceptionalT e m)
instance (Functor m) => Functor (ExceptionalT e m)
instance MonadFix (Exceptional e)
instance Monad (Exceptional e)
instance Applicative (Exceptional e)
instance Functor (Exceptional e)
-- | Asynchronous exceptions can occur during the construction of a lazy
-- data structure. They are represented by a lazy data structure itself.
--
-- TODO:
--
--
-- - Check whether laziness behaviour is reasonable.
--
module Control.Monad.Exception.Asynchronous
-- | Contains a value and a reason why the computation of the value of type
-- a was terminated. Imagine a as a list type, and an
-- according operation like the readFile operation. If the
-- exception part is Nothing then the value could be constructed
-- regularly. If the exception part is Just then the value could
-- not be constructed completely. However you can read the result of type
-- a lazily, even if an exception occurs while it is evaluated.
-- If you evaluate the exception part, then the result value is certainly
-- computed completely.
--
-- However, we cannot provide general Monad functionality due to
-- the very different ways of combining the results of type a.
-- It is recommended to process the result value in an application
-- specific way, and after consumption of the result, throw a synchronous
-- exception using toSynchronous.
--
-- Maybe in the future we provide a monad instance which considers
-- subsequent actions as simultaneous processes on a lazy data structure.
data Exceptional e a
Exceptional :: Maybe e -> a -> Exceptional e a
exception :: Exceptional e a -> Maybe e
result :: Exceptional e a -> a
-- | Create an exceptional value without exception.
pure :: a -> Exceptional e a
-- | Create an exceptional value with exception.
broken :: e -> a -> Exceptional e a
fromSynchronous :: a -> Exceptional e a -> Exceptional e a
fromSynchronousNull :: Exceptional e () -> Exceptional e ()
fromSynchronousMonoid :: (Monoid a) => Exceptional e a -> Exceptional e a
toSynchronous :: Exceptional e a -> Exceptional e a
throw :: e -> Exceptional e ()
throwMonoid :: (Monoid a) => e -> Exceptional e a
-- | Repeat an action with synchronous exceptions until an exception
-- occurs. Combine all atomic results using the bind function.
-- It may be cons = (:) and empty = [] for b
-- being a list type. The defer function may be id or
-- unsafeInterleaveIO for lazy read operations. The exception is
-- returned as asynchronous exception.
manySynchronousT :: (Monad m) => (m (Exceptional e b) -> m (Exceptional e b)) -> (a -> b -> b) -> b -> ExceptionalT e m a -> m (Exceptional e b)
-- | Scan x using the decons function and run an action
-- with synchronous exceptions for each element fetched from x.
-- Each invocation of an element action may stop this function due to an
-- exception. If all element action can be performed successfully and if
-- there is an asynchronous exception then at the end this exception is
-- raised as synchronous exception. decons function might be
-- viewL.
processToSynchronousT_ :: (Monad m) => (b -> Maybe (a, b)) -> (a -> ExceptionalT e m ()) -> Exceptional e b -> ExceptionalT e m ()
-- | This is an example for application specific handling of result values.
-- Assume you obtain two lazy lists say from readFile and you want
-- to zip their contents. If one of the stream readers emits an
-- exception, we quit with that exception. If both streams have throw an
-- exception at the same file position, the exception of the first stream
-- is propagated.
zipWith :: (a -> b -> c) -> Exceptional e [a] -> Exceptional e [b] -> Exceptional e [c]
-- | This is an example for application specific handling of result values.
-- Assume you obtain two lazy lists say from readFile and you want
-- to append their contents. If the first stream ends with an exception,
-- this exception is kept and the second stream is not touched. If the
-- first stream can be read successfully, the second one is appended
-- until stops.
append :: (Monoid a) => Exceptional e a -> Exceptional e a -> Exceptional e a
continue :: (Monoid a) => Maybe e -> Exceptional e a -> Exceptional e a
maybeAbort :: Exceptional e a -> Maybe e -> Exceptional e a
-- | construct Exceptional constructor lazily
force :: Exceptional e a -> Exceptional e a
mapException :: (e0 -> e1) -> Exceptional e0 a -> Exceptional e1 a
mapExceptional :: (e0 -> e1) -> (a -> b) -> Exceptional e0 a -> Exceptional e1 b
-- | I consider both actions to process the data simultaneously through
-- lazy evaluation. If the second one fails too, it must have encountered
-- an exception in the data that was successfully emitted by the first
-- action, and thus the exception of the second action is probably
-- earlier.
--
-- We cannot check in general whether the two exception occur at the same
-- time, e.g. the second one might occur since the first occured and left
-- an invalid structure. In this case we should emit the first exception,
-- not the second one. Because of this I expect that this function is not
-- particularly useful. Otherwise it could be used as bind operation for
-- a monad instance.
simultaneousBind :: Exceptional e a -> (a -> Exceptional e b) -> Exceptional e b
simultaneousBindM :: (Monad m) => m (Exceptional e a) -> (a -> m (Exceptional e b)) -> m (Exceptional e b)
-- | Foldable instance would allow to strip off the exception too
-- easily.
--
-- I like the methods of Traversable, but Traversable
-- instance requires Foldable instance.
traverse :: (Applicative f) => (a -> f b) -> Exceptional e a -> f (Exceptional e b)
sequenceA :: (Applicative f) => Exceptional e (f a) -> f (Exceptional e a)
mapM :: (Monad m) => (a -> m b) -> Exceptional e a -> m (Exceptional e b)
sequence :: (Monad m) => Exceptional e (m a) -> m (Exceptional e a)
-- | Consider a file format consisting of a header and a data body. The
-- header can only be used if is read completely. Its parsing might stop
-- with an synchronous exception. The data body can also be used if it is
-- truncated by an exceptional event. This is expressed by an
-- asynchronous exception. A loader for this file format can thus fail by
-- a synchronous and an asynchronous exception. Surprisingly, both orders
-- of nesting these two kinds of exceptional actions are equally
-- expressive. This function converts to the form where the synchronous
-- exception is the outer one.
swapToSynchronousAsynchronous :: Exceptional e0 (Exceptional e1 a) -> Exceptional e1 (Exceptional e0 a)
swapToAsynchronousSynchronous :: Exceptional e1 (Exceptional e0 a) -> Exceptional e0 (Exceptional e1 a)
instance (Show e, Show a) => Show (Exceptional e a)
instance Functor (Exceptional e)