Maintainer | dneavesdev@pm.me |
---|---|
Safe Haskell | Safe |
Language | GHC2021 |
Antelude.IO
Description
Synopsis
- data IO a
- type IOError = IOException
- class Monad m => MonadIO (m :: Type -> Type) where
- class (Typeable e, Show e) => Exception e
- error :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => [Char] -> a
- errorWithoutStackTrace :: forall (r :: RuntimeRep) (a :: TYPE r). [Char] -> a
- getChar :: IO Char
- getContents :: IO String
- getLine :: IO String
- interact :: (String -> String) -> IO ()
- ioError :: IOError -> IO a
- putChar :: Char -> IO ()
- putStr :: String -> IO ()
- putStrLn :: String -> IO ()
- readIO :: Read a => String -> IO a
- readLn :: Read a => IO a
- undefined :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => a
- userError :: String -> IOError
- try :: Exception e => IO a -> IO (Either e a)
- handle :: Exception e => (e -> IO a) -> IO a -> IO a
- catch :: Exception e => IO a -> (e -> IO a) -> IO a
Documentation
A value of type
is a computation which, when performed,
does some I/O before returning a value of type IO
aa
.
There is really only one way to "perform" an I/O action: bind it to
Main.main
in your program. When your program is run, the I/O will
be performed. It isn't possible to perform I/O from an arbitrary
function, unless that function is itself in the IO
monad and called
at some point, directly or indirectly, from Main.main
.
IO
is a monad, so IO
actions can be combined using either the do-notation
or the >>
and >>=
operations from the Monad
class.
Instances
MonadFail IO | Since: base-4.9.0.0 |
Defined in Control.Monad.Fail | |
MonadIO IO | Since: base-4.9.0.0 |
Defined in Control.Monad.IO.Class | |
Alternative IO | Takes the first non-throwing Since: base-4.9.0.0 |
Applicative IO | Since: base-2.1 |
Functor IO | Since: base-2.1 |
Monad IO | Since: base-2.1 |
MonadPlus IO | Takes the first non-throwing Since: base-4.9.0.0 |
Monoid a => Monoid (IO a) | Since: base-4.9.0.0 |
Semigroup a => Semigroup (IO a) | Since: base-4.10.0.0 |
type IOError = IOException #
The Haskell 2010 type for exceptions in the IO
monad.
Any I/O operation may raise an IOException
instead of returning a result.
For a more general type of exception, including also those that arise
in pure code, see Exception
.
In Haskell 2010, this is an opaque type.
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:
Methods
Lift a computation from the IO
monad.
This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations
(i.e. IO
is the base monad for the stack).
Example
import Control.Monad.Trans.State -- from the "transformers" library printState :: Show s => StateT s IO () printState = do state <- get liftIO $ print state
Had we omitted
, we would have ended up with this error:liftIO
• Couldn't match type ‘IO’ with ‘StateT s IO’ Expected type: StateT s IO () Actual type: IO ()
The important part here is the mismatch between StateT s IO ()
and
.IO
()
Luckily, we know of a function that takes an
and returns an IO
a(m a)
:
,
enabling us to run the program and see the expected results:liftIO
> evalStateT printState "hello" "hello" > evalStateT printState 3 3
Reexport from Exception
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
Reexport from Prelude
error :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => [Char] -> a #
error
stops execution and displays an error message.
Reexport from Prelude
errorWithoutStackTrace :: forall (r :: RuntimeRep) (a :: TYPE r). [Char] -> a #
A variant of error
that does not produce a stack trace.
Since: base-4.9.0.0
Reexport from Prelude
Reexport from Prelude
getContents :: IO String #
The getContents
operation returns all user input as a single string,
which is read lazily as it is needed
(same as hGetContents
stdin
).
Reexport from Prelude
Reexport from Prelude
interact :: (String -> String) -> IO () #
The interact
function takes a function of type String->String
as its argument. The entire input from the standard input device is
passed to this function as its argument, and the resulting string is
output on the standard output device.
Reexport from Prelude
Reexport from Prelude
Reexport from Preluded
Reexport from Preluded
Reexport from Preluded
Reexport from Preluded
Reexport from Preluded
undefined :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => a #
Reexport from Preluded
userError :: String -> IOError #
Construct an IOException
value with a string describing the error.
The fail
method of the IO
instance of the Monad
class raises a
userError
, thus:
instance Monad IO where ... fail s = ioError (userError s)
Reexport from Exception
try :: Exception e => IO a -> IO (Either e a) #
Similar to catch
, but returns an Either
result which is
(
if no exception of type Right
a)e
was raised, or (
if an exception of type Left
ex)e
was raised and its value is ex
.
If any other type of exception is raised then it will be propagated
up to the next enclosing exception handler.
try a = catch (Right `liftM` a) (return . Left)
Reexport from Exception
handle :: Exception e => (e -> IO a) -> IO a -> IO a #
A version of catch
with the arguments swapped around; useful in
situations where the code for the handler is shorter. For example:
do handle (\NonTermination -> exitWith (ExitFailure 1)) $ ...
Reexport from Exception
Arguments
:: 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 propagated further up. If you call it again, you
might get the opposite behaviour. This is ok, because catch
is an
IO
computation.