Safe Haskell | None |
---|---|
Language | Haskell2010 |
- class MonadEffect (Signal a b) m => MonadEffectSignal a b m where
- data ResumeOrBreak b c
- throwSignal :: Throws a m => a -> m b
- handleSignal :: Monad m => (a -> m (ResumeOrBreak b c)) -> EffectHandler (Signal a b) (ExceptT c m) c -> m c
- type Throws e m = MonadEffectSignal e Void m
- handleException :: Monad m => (a -> m c) -> ExceptT a m c -> m c
- handleToEither :: ExceptT e m a -> m (Either e a)
- module Control.Effects
- module Control.Monad.Trans.Except
- newtype MaybeT m a :: (* -> *) -> * -> * = MaybeT {}
- discardAllExceptions :: MaybeT m a -> m (Maybe a)
- showAllExceptions :: Functor m => ExceptT SomeSignal m a -> m (Either Text a)
- class Throws e m => Handles e m where
- handleToEitherRecursive :: Handles e m => m a -> m (Either e a)
- data SomeSignal
Documentation
class MonadEffect (Signal a b) m => MonadEffectSignal a b m where Source #
This class allows you to "throw" a signal. For the most part signals are the same as checked
exceptions. The difference here is that the handler has the option to provide the value that
will be the result of calling the signal
function. This effectively allows you to have
recoverable exceptions at the call site, instead of just at the handling site.
This class can be considered an alias for
so your code isn't
required to provide any instances.MonadEffect
(Signal
a b)
There are no restrictions on the type of values that can be thrown or returned.
MonadEffect (Signal a b) IO => MonadEffectSignal a b IO Source # | |
(MonadEffectSignal a b m, MonadTrans t, Monad (t m)) => MonadEffectSignal a b (t m) Source # | |
Monad m => MonadEffectSignal a b (MaybeT m) Source # | |
(Monad m, Show e) => MonadEffectSignal e b (ExceptT SomeSignal m) Source # | |
Monad m => MonadEffectSignal e b (ExceptT e m) Source # | |
data ResumeOrBreak b c Source #
The handle function will return a value of this type.
throwSignal :: Throws a m => a -> m b Source #
handleSignal :: Monad m => (a -> m (ResumeOrBreak b c)) -> EffectHandler (Signal a b) (ExceptT c m) c -> m c Source #
Handle signals of a computation. The handler function has the option to provide a value
to the caller of signal
and continue execution there, or do what regular exception handlers
do and continue execution after the handler.
type Throws e m = MonadEffectSignal e Void m Source #
handleException :: Monad m => (a -> m c) -> ExceptT a m c -> m c Source #
This handler can only behave like a regular exception handler. If used along with throwSignal
this module behaves like regular checked exceptions.
handleToEither :: ExceptT e m a -> m (Either e a) Source #
See documentation for handleException
. This handler gives you an Either
.
module Control.Effects
module Control.Monad.Trans.Except
newtype MaybeT m a :: (* -> *) -> * -> * #
The parameterizable maybe monad, obtained by composing an arbitrary
monad with the Maybe
monad.
Computations are actions that may produce a value or exit.
The return
function yields a computation that produces that
value, while >>=
sequences two subcomputations, exiting if either
computation does.
discardAllExceptions :: MaybeT m a -> m (Maybe a) Source #
Discard all the Throws
and MonadEffectSignal
constraints. If any exception was thrown
the result will be Nothing
.
showAllExceptions :: Functor m => ExceptT SomeSignal m a -> m (Either Text a) Source #
Satisfies all the Throws
and MonadEffectSignal
constraints if they all throw Show
able
exceptions. The first thrown exception will be shown and returned as a Left
result.
class Throws e m => Handles e m where Source #
A class of monads that throw and catch exceptions of type e
. An overlappable instance is
given so you just need to make sure your transformers have a RunnableTrans
instance.
handleRecursive :: (e -> m a) -> m a -> m a Source #
Use this function to handle exceptions without discarding the Throws
constraint.
You'll want to use this if you're writing a recursive function. Using the regular handlers
in that case will result with infinite types.
Since this function doesn't discard constraints, you still need to handle the whole thing.
Here's a slightly contrived example.
data NotFound = NotFound data Tree a = Leaf a | Node (Tree a) (Tree a) data Step = GoLeft | GoRight findIndex :: (Handles NotFound m, Eq a) => a -> Tree a -> m [Step] findIndex x (Leaf a) | x == a = return [] | otherwise = throwSignal NotFound findIndex x (Node l r) = ((GoLeft :) $ findIndex x l) & handleRecursive (NotFound -> (GoRight :) $ findIndex x r)
Note: When you finally handle the exception effect, the order in which you handle it and
other effects determines whether handleRecursive
rolls back other effects if an exception
occured or it preserves all of them up to the point of the exception.
Handling exceptions last and handling them first will produce the former and latter
behaviour respectively.
handleToEitherRecursive :: Handles e m => m a -> m (Either e a) Source #
handleToEither
that doesn't discard Throws
constraints. See documentation for
handleRecursive
.
data SomeSignal Source #
Eq SomeSignal Source # | |
Ord SomeSignal Source # | |
Read SomeSignal Source # | |
Show SomeSignal Source # | |
(Monad m, Show e) => MonadEffectSignal e b (ExceptT SomeSignal m) Source # | |