Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- type ErrIO = ErrorT Text IO
- type ErrOrVal = Either Text
- toErrOrVal :: Either String a -> ErrOrVal a
- runErr :: ErrIO a -> IO (ErrOrVal a)
- runErrorVoid :: ErrIO () -> IO ()
- undef :: Text -> a
- fromRightEOV :: ErrOrVal a -> a
- bracketErrIO :: ErrIO a -> (a -> ErrIO b) -> (a -> ErrIO c) -> ErrIO c
- callIO :: (MonadError m, MonadIO m, ErrorType m ~ Text) => IO a -> m a
- throwErrorT :: [Text] -> ErrIO a
- maybe2error :: Maybe a -> ErrIO a
- errorT :: [Text] -> a
- errorWords :: [Text] -> a
- fromJustNoteT :: [Text] -> Maybe a -> a
- fromRightNoteString :: Text -> Either String b -> b
- fromRightNote :: Text -> Either Text b -> b
- headNoteT :: [Text] -> [a] -> a
- startProg :: Show a => Text -> ErrIO a -> IO ()
- readNote :: (Partial, Read a) => String -> String -> a
- headNote :: Partial => String -> [a] -> a
- class Monad m => MonadIO (m :: Type -> Type) where
- unless :: Applicative f => Bool -> f () -> f ()
- when :: Applicative f => Bool -> f () -> f ()
- class Error a
- data ErrorT e (m :: Type -> Type) a
- type family ErrorType (m :: Type -> Type)
- class Monad m => MonadError (m :: Type -> Type) where
- type ErrorType (m :: Type -> Type)
- throwError :: ErrorType m -> m a
- catchError :: m a -> (ErrorType m -> m a) -> m a
- bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
- catch :: Exception e => IO a -> (e -> IO a) -> IO a
- class (Typeable e, Show e) => Exception e
- data SomeException
Documentation
runErr :: ErrIO a -> IO (ErrOrVal a) Source #
runErr to avoid the depreceated message for runErrorT, which is identical
runErrorVoid :: ErrIO () -> IO () Source #
run an operation in ErrIO which is not returning anything simpler to use than runErr
fromRightEOV :: ErrOrVal a -> a Source #
callIO :: (MonadError m, MonadIO m, ErrorType m ~ Text) => IO a -> m a Source #
this is using catch to grab all errors
throwErrorT :: [Text] -> ErrIO a Source #
maybe2error :: Maybe a -> ErrIO a Source #
errorWords :: [Text] -> a Source #
fromJustNoteT :: [Text] -> Maybe a -> a Source #
readNote :: (Partial, Read a) => String -> String -> a #
readNote
uses readEitherSafe
for the error message.
class Monad m => MonadIO (m :: Type -> Type) where #
Monads in which IO
computations may be embedded.
Any monad built by applying a sequence of monad transformers to the
IO
monad will be an instance of this class.
Instances should satisfy the following laws, which state that liftIO
is a transformer of monads:
Instances
unless :: Applicative f => Bool -> f () -> f () #
The reverse of when
.
when :: Applicative f => Bool -> f () -> f () #
Conditional execution of Applicative
expressions. For example,
when debug (putStrLn "Debugging")
will output the string Debugging
if the Boolean value debug
is True
, and otherwise do nothing.
Instances
Error Text Source # | |
Error IOException | |
Defined in Control.Monad.Trans.Error noMsg :: IOException # strMsg :: String -> IOException # | |
ErrorList a => Error [a] | A string can be thrown as an error. |
data ErrorT e (m :: Type -> Type) a #
The error monad transformer. It can be used to add error handling to other monads.
The ErrorT
Monad structure is parameterized over two things:
- e - The error type.
- m - The inner monad.
The return
function yields a successful computation, while >>=
sequences two subcomputations, failing on the first error.
Instances
type family ErrorType (m :: Type -> Type) #
Instances
type ErrorType IO | |
Defined in Control.Monad.Error.Class | |
type ErrorType (Either e) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (ListT m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (MaybeT m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (WriterT w m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (StateT s m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (ReaderT r m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (ErrorT e m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (IdentityT m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (StateT s m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (WriterT w m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (RWST r w s m) | |
Defined in Control.Monad.Error.Class | |
type ErrorType (RWST r w s m) | |
Defined in Control.Monad.Error.Class |
class Monad m => MonadError (m :: Type -> Type) where #
The strategy of combining computations that can throw exceptions by bypassing bound functions from the point an exception is thrown to the point that it is handled.
Is parameterized over the type of error information and
the monad type constructor.
It is common to use
as the monad type constructor
for an error monad in which error descriptions take the form of strings.
In that case and many other common cases the resulting monad is already defined
as an instance of the Either
StringMonadError
class.
You can also define your own error type and/or use a monad type constructor
other than
or Either
String
.
In these cases you will have to explicitly define instances of the Either
IOErrorError
and/or MonadError
classes.
throwError :: ErrorType m -> m a #
Is used within a monadic computation to begin exception processing.
catchError :: m a -> (ErrorType m -> m a) -> m a #
A handler function to handle previous errors and return to normal execution. A common idiom is:
do { action1; action2; action3 } `catchError` handler
where the action
functions can call throwError
.
Note that handler
and the do-block must have the same return type.
Instances
MonadError IO | |
Error e => MonadError (Either e) | |
MonadError m => MonadError (ListT m) | |
MonadError m => MonadError (MaybeT m) | |
(Monoid w, MonadError m) => MonadError (WriterT w m) | |
MonadError m => MonadError (StateT s m) | |
MonadError m => MonadError (ReaderT r m) | |
(Monad m, Error e) => MonadError (ErrorT e m) | |
MonadError m => MonadError (IdentityT m) | |
MonadError m => MonadError (StateT s m) | |
(Monoid w, MonadError m) => MonadError (WriterT w m) | |
(Monoid w, MonadError m) => MonadError (RWST r w s m) | |
(Monoid w, MonadError m) => MonadError (RWST r w s m) | |
:: IO a | computation to run first ("acquire resource") |
-> (a -> IO b) | computation to run last ("release resource") |
-> (a -> IO c) | computation to run in-between |
-> IO c |
When you want to acquire a resource, do some work with it, and
then release the resource, it is a good idea to use bracket
,
because bracket
will install the necessary exception handler to
release the resource in the event that an exception is raised
during the computation. If an exception is raised, then bracket
will
re-raise the exception (after performing the release).
A common example is opening a file:
bracket (openFile "filename" ReadMode) (hClose) (\fileHandle -> do { ... })
The arguments to bracket
are in this order so that we can partially apply
it, e.g.:
withFile name mode = bracket (openFile name mode) hClose
:: Exception e | |
=> IO a | The computation to run |
-> (e -> IO a) | Handler to invoke if an exception is raised |
-> IO a |
This is the simplest of the exception-catching functions. It takes a single argument, runs it, and if an exception is raised the "handler" is executed, with the value of the exception passed as an argument. Otherwise, the result is returned as normal. For example:
catch (readFile f) (\e -> do let err = show (e :: IOException) hPutStr stderr ("Warning: Couldn't open " ++ f ++ ": " ++ err) return "")
Note that we have to give a type signature to e
, or the program
will not typecheck as the type is ambiguous. While it is possible
to catch exceptions of any type, see the section "Catching all
exceptions" (in Control.Exception) for an explanation of the problems with doing so.
For catching exceptions in pure (non-IO
) expressions, see the
function evaluate
.
Note that due to Haskell's unspecified evaluation order, an
expression may throw one of several possible exceptions: consider
the expression (error "urk") + (1 `div` 0)
. Does
the expression throw
ErrorCall "urk"
, or DivideByZero
?
The answer is "it might throw either"; the choice is
non-deterministic. If you are catching any type of exception then you
might catch either. If you are calling catch
with type
IO Int -> (ArithException -> IO Int) -> IO Int
then the handler may
get run with DivideByZero
as an argument, or an ErrorCall "urk"
exception may be propogated further up. If you call it again, you
might get a the opposite behaviour. This is ok, because catch
is an
IO
computation.
class (Typeable e, Show e) => Exception e #
Any type that you wish to throw or catch as an exception must be an
instance of the Exception
class. The simplest case is a new exception
type directly below the root:
data MyException = ThisException | ThatException deriving Show instance Exception MyException
The default method definitions in the Exception
class do what we need
in this case. You can now throw and catch ThisException
and
ThatException
as exceptions:
*Main> throw ThisException `catch` \e -> putStrLn ("Caught " ++ show (e :: MyException)) Caught ThisException
In more complicated examples, you may wish to define a whole hierarchy of exceptions:
--------------------------------------------------------------------- -- Make the root exception type for all the exceptions in a compiler data SomeCompilerException = forall e . Exception e => SomeCompilerException e instance Show SomeCompilerException where show (SomeCompilerException e) = show e instance Exception SomeCompilerException compilerExceptionToException :: Exception e => e -> SomeException compilerExceptionToException = toException . SomeCompilerException compilerExceptionFromException :: Exception e => SomeException -> Maybe e compilerExceptionFromException x = do SomeCompilerException a <- fromException x cast a --------------------------------------------------------------------- -- Make a subhierarchy for exceptions in the frontend of the compiler data SomeFrontendException = forall e . Exception e => SomeFrontendException e instance Show SomeFrontendException where show (SomeFrontendException e) = show e instance Exception SomeFrontendException where toException = compilerExceptionToException fromException = compilerExceptionFromException frontendExceptionToException :: Exception e => e -> SomeException frontendExceptionToException = toException . SomeFrontendException frontendExceptionFromException :: Exception e => SomeException -> Maybe e frontendExceptionFromException x = do SomeFrontendException a <- fromException x cast a --------------------------------------------------------------------- -- Make an exception type for a particular frontend compiler exception data MismatchedParentheses = MismatchedParentheses deriving Show instance Exception MismatchedParentheses where toException = frontendExceptionToException fromException = frontendExceptionFromException
We can now catch a MismatchedParentheses
exception as
MismatchedParentheses
, SomeFrontendException
or
SomeCompilerException
, but not other types, e.g. IOException
:
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: MismatchedParentheses)) Caught MismatchedParentheses *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeFrontendException)) Caught MismatchedParentheses *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeCompilerException)) Caught MismatchedParentheses *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: IOException)) *** Exception: MismatchedParentheses
Instances
data SomeException #
The SomeException
type is the root of the exception type hierarchy.
When an exception of type e
is thrown, behind the scenes it is
encapsulated in a SomeException
.
Instances
Show SomeException | Since: base-3.0 |
Defined in GHC.Exception.Type showsPrec :: Int -> SomeException -> ShowS # show :: SomeException -> String # showList :: [SomeException] -> ShowS # | |
Exception SomeException | Since: base-3.0 |
Defined in GHC.Exception.Type |