IO.hs

    {-# LANGUAGE CPP #-}
    #if __GLASGOW_HASKELL__ >= 701
    {-# LANGUAGE Safe #-}
    #endif

    module IO (
            Handle, HandlePosn,
            IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
            BufferMode(NoBuffering,LineBuffering,BlockBuffering),
            SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
            stdin, stdout, stderr,
            openFile, hClose, hFileSize, hIsEOF, isEOF,
            hSetBuffering, hGetBuffering, hFlush,
            hGetPosn, hSetPosn, hSeek,
            hWaitForInput, hReady, hGetChar, hGetLine, hLookAhead, hGetContents,
            hPutChar, hPutStr, hPutStrLn, hPrint,
            hIsOpen, hIsClosed, hIsReadable, hIsWritable, hIsSeekable,
            isAlreadyExistsError, isDoesNotExistError, isAlreadyInUseError,
            isFullError, isEOFError,
            isIllegalOperation, isPermissionError, isUserError,
            ioeGetErrorString, ioeGetHandle, ioeGetFileName,
            try, bracket, bracket_,

            -- ...and what the Prelude exports
            IO, FilePath, IOError, ioError, userError, catch, interact,
            putChar, putStr, putStrLn, print, getChar, getLine, getContents,
            readFile, writeFile, appendFile, readIO, readLn
        ) where

    import System.IO
    import System.IO.Error

    -- | The 'bracket' function captures a common allocate, compute, deallocate
    -- idiom in which the deallocation step must occur even in the case of an
    -- error during computation. This is similar to try-catch-finally in Java.
    --
    -- This version handles only IO errors, as defined by Haskell 98.
    -- The version of @bracket@ in "Control.Exception" handles all exceptions,
    -- and should be used instead.

    bracket        :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
    bracket before after m = do
            x  <- before
            rs <- try (m x)
            _ <- after x
            case rs of
               Right r -> return r
               Left  e -> ioError e

    -- | A variant of 'bracket' where the middle computation doesn't want @x@.
    --
    -- This version handles only IO errors, as defined by Haskell 98.
    -- The version of @bracket_@ in "Control.Exception" handles all exceptions,
    -- and should be used instead.

    bracket_        :: IO a -> (a -> IO b) -> IO c -> IO c
    bracket_ before after m = do
             x  <- before
             rs <- try m
             _ <- after x
             case rs of
                Right r -> return r
                Left  e -> ioError e

    -- | The construct 'try' @comp@ exposes IO errors which occur within a
    -- computation, and which are not fully handled.
    --
    -- Non-I\/O exceptions are not caught by this variant; to catch all
    -- exceptions, use 'Control.Exception.try' from "Control.Exception".
    try     :: IO a -> IO (Either IOError a)
    try f   =  catch (do r <- f
                         return (Right r))
                     (return . Left)