{-# LANGUAGE Unsafe #-}{-# LANGUAGE NoImplicitPrelude
 , BangPatterns
 , RankNTypes
 , MagicHash
 , ScopedTypeVariables
 , UnboxedTuples
 #-}{-# OPTIONS_GHC -funbox-strict-fields #-}{-# OPTIONS_HADDOCK hide #-}------------------------------------------------------------------------------- |-- Module : GHC.IO-- Copyright : (c) The University of Glasgow 1994-2002-- License : see libraries/base/LICENSE---- Maintainer : cvs-ghc@haskell.org-- Stability : internal-- Portability : non-portable (GHC Extensions)---- Definitions for the 'IO' monad and its friends.-------------------------------------------------------------------------------moduleGHC.IO(IO(..),unIO ,failIO ,liftIO ,mplusIO ,unsafePerformIO ,unsafeInterleaveIO ,unsafeDupablePerformIO ,unsafeDupableInterleaveIO ,noDuplicate ,-- To and from from STstToIO ,ioToST ,unsafeIOToST ,unsafeSTToIO ,FilePath ,catch ,catchException ,catchAny ,throwIO ,mask ,mask_ ,uninterruptibleMask ,uninterruptibleMask_ ,MaskingState (..),getMaskingState ,unsafeUnmask ,interruptible ,onException ,bracket ,finally ,evaluate )whereimportGHC.Base importGHC.ST importGHC.Exception importGHC.Show importGHC.IO.Unsafe import{-# SOURCE#-}GHC.IO.Exception (userError ,IOError )-- ----------------------------------------------------------------------------- The IO Monad{-
The IO Monad is just an instance of the ST monad, where the state is
the real world. We use the exception mechanism (in GHC.Exception) to
implement IO exceptions.
NOTE: The IO representation is deeply wired in to various parts of the
system. The following list may or may not be exhaustive:
Compiler - types of various primitives in PrimOp.hs
RTS - forceIO (StgStartup.cmm)
 - catchzh_fast, (un)?blockAsyncExceptionszh_fast, raisezh_fast
 (Exception.cmm)
 - raiseAsync (RaiseAsync.c)
Prelude - GHC.IO.hs, and several other places including
 GHC.Exception.hs.
Libraries - parts of hslibs/lang.
--SDM
-}liftIO::IOa ->State#RealWorld->STret RealWorlda liftIO (IOm )=\s ->casem s of(#s' ,r #)->STret s' r failIO::String ->IOa failIO s =IO(raiseIO#(toException (userError s )))-- ----------------------------------------------------------------------------- Coercions between IO and ST-- | Embed a strict state transformer in an 'IO'-- action. The 'RealWorld' parameter indicates that the internal state-- used by the 'ST' computation is a special one supplied by the 'IO'-- monad, and thus distinct from those used by invocations of 'runST'.stToIO::ST RealWorlda ->IOa stToIO (ST m )=IOm -- | Convert an 'IO' action into an 'ST' action. The type of the result-- is constrained to use a 'RealWorld' state, and therefore the result cannot-- be passed to 'runST'.ioToST::IOa ->ST RealWorlda ioToST (IOm )=(ST m )-- | Convert an 'IO' action to an 'ST' action.-- This relies on 'IO' and 'ST' having the same representation modulo the-- constraint on the type of the state.unsafeIOToST::IOa ->ST s a unsafeIOToST (IOio )=ST $ \s ->(unsafeCoerce#io )s -- | Convert an 'ST' action to an 'IO' action.-- This relies on 'IO' and 'ST' having the same representation modulo the-- constraint on the type of the state.---- For an example demonstrating why this is unsafe, see-- https://mail.haskell.org/pipermail/haskell-cafe/2009-April/060719.htmlunsafeSTToIO::ST s a ->IOa unsafeSTToIO (ST m )=IO(unsafeCoerce#m )-- ------------------------------------------------------------------------------- | File and directory names are values of type 'String', whose precise-- meaning is operating system dependent. Files can be opened, yielding a-- handle which can then be used to operate on the contents of that file.typeFilePath =String -- ------------------------------------------------------------------------------- Primitive catch and throwIO{-
catchException/catch used to handle the passing around of the state to the
action and the handler. This turned out to be a bad idea - it meant
that we had to wrap both arguments in thunks so they could be entered
as normal (remember IO returns an unboxed pair...).
Now catch# has type
 catch# :: IO a -> (b -> IO a) -> IO a
(well almost; the compiler doesn't know about the IO newtype so we
have to work around that in the definition of catch below).
-}-- | Catch an exception in the 'IO' monad.---- Note that this function is /strict/ in the action. That is,-- @catchException undefined b == _|_@. See #exceptions_and_strictness#-- for details.catchException::Exception e =>IOa ->(e ->IOa )->IOa catchException !io handler =catch io handler -- | 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.--catch::Exception e =>IOa -- ^ The computation to run->(e ->IOa )-- ^ Handler to invoke if an exception is raised->IOa -- See #exceptions_and_strictness#.catch (IOio )handler =IO$ catch#io handler' wherehandler' e =casefromException e ofJust e' ->unIO (handler e' )Nothing ->raiseIO#e -- | Catch any 'Exception' type in the 'IO' monad.---- Note that this function is /strict/ in the action. That is,-- @catchAny undefined b == _|_@. See #exceptions_and_strictness# for-- details.catchAny::IOa ->(foralle .Exception e =>e ->IOa )->IOa catchAny !(IOio )handler =IO$ catch#io handler' wherehandler' (SomeException e )=unIO (handler e )-- Using catchException here means that if `m` throws an-- 'IOError' /as an imprecise exception/, we will not catch-- it. No one should really be doing that anyway.mplusIO::IOa ->IOa ->IOa mplusIO m n =m `catchException `\(_::IOError )->n -- | A variant of 'throw' that can only be used within the 'IO' monad.---- Although 'throwIO' has a type that is an instance of the type of 'throw', the-- two functions are subtly different:---- > throw e `seq` x ===> throw e-- > throwIO e `seq` x ===> x---- The first example will cause the exception @e@ to be raised,-- whereas the second one won\'t. In fact, 'throwIO' will only cause-- an exception to be raised when it is used within the 'IO' monad.-- The 'throwIO' variant should be used in preference to 'throw' to-- raise an exception within the 'IO' monad because it guarantees-- ordering with respect to other 'IO' operations, whereas 'throw'-- does not.throwIO::Exception e =>e ->IOa throwIO e =IO(raiseIO#(toException e ))-- ------------------------------------------------------------------------------- Controlling asynchronous exception delivery-- Applying 'block' to a computation will-- execute that computation with asynchronous exceptions-- /blocked/. That is, any thread which-- attempts to raise an exception in the current thread with 'Control.Exception.throwTo' will be-- blocked until asynchronous exceptions are unblocked again. There\'s-- no need to worry about re-enabling asynchronous exceptions; that is-- done automatically on exiting the scope of-- 'block'.---- Threads created by 'Control.Concurrent.forkIO' inherit the blocked-- state from the parent; that is, to start a thread in blocked mode,-- use @block $ forkIO ...@. This is particularly useful if you need to-- establish an exception handler in the forked thread before any-- asynchronous exceptions are received.block::IOa ->IOa block (IOio )=IO$ maskAsyncExceptions#io -- To re-enable asynchronous exceptions inside the scope of-- 'block', 'unblock' can be-- used. It scopes in exactly the same way, so on exit from-- 'unblock' asynchronous exception delivery will-- be disabled again.unblock::IOa ->IOa unblock =unsafeUnmask unsafeUnmask::IOa ->IOa unsafeUnmask (IOio )=IO$ unmaskAsyncExceptions#io -- | Allow asynchronous exceptions to be raised even inside 'mask', making-- the operation interruptible (see the discussion of "Interruptible operations"-- in 'Control.Exception').---- When called outside 'mask', or inside 'uninterruptibleMask', this-- function has no effect.---- @since 4.9.0.0interruptible::IOa ->IOa interruptible act =dost <-getMaskingState casest ofUnmasked ->act MaskedInterruptible ->unsafeUnmask act MaskedUninterruptible ->act blockUninterruptible::IOa ->IOa blockUninterruptible (IOio )=IO$ maskUninterruptible#io -- | Describes the behaviour of a thread when an asynchronous-- exception is received.dataMaskingState =Unmasked -- ^ asynchronous exceptions are unmasked (the normal state)|MaskedInterruptible -- ^ the state during 'mask': asynchronous exceptions are masked, but blocking operations may still be interrupted|MaskedUninterruptible -- ^ the state during 'uninterruptibleMask': asynchronous exceptions are masked, and blocking operations may not be interruptedderiving(Eq-- ^ @since 4.3.0.0,Show -- ^ @since 4.3.0.0)-- | Returns the 'MaskingState' for the current thread.getMaskingState::IOMaskingState getMaskingState =IO$ \s ->casegetMaskingState#s of(#s' ,i #)->(#s' ,casei of0#->Unmasked 1#->MaskedUninterruptible _->MaskedInterruptible #)onException::IOa ->IOb ->IOa onException io what =io `catchException `\e ->do_<-what throwIO (e ::SomeException )-- | Executes an IO computation with asynchronous-- exceptions /masked/. That is, any thread which attempts to raise-- an exception in the current thread with 'Control.Exception.throwTo'-- will be blocked until asynchronous exceptions are unmasked again.---- The argument passed to 'mask' is a function that takes as its-- argument another function, which can be used to restore the-- prevailing masking state within the context of the masked-- computation. For example, a common way to use 'mask' is to protect-- the acquisition of a resource:---- > mask $ \restore -> do-- > x <- acquire-- > restore (do_something_with x) `onException` release-- > release---- This code guarantees that @acquire@ is paired with @release@, by masking-- asynchronous exceptions for the critical parts. (Rather than write-- this code yourself, it would be better to use-- 'Control.Exception.bracket' which abstracts the general pattern).---- Note that the @restore@ action passed to the argument to 'mask'-- does not necessarily unmask asynchronous exceptions, it just-- restores the masking state to that of the enclosing context. Thus-- if asynchronous exceptions are already masked, 'mask' cannot be used-- to unmask exceptions again. This is so that if you call a library function-- with exceptions masked, you can be sure that the library call will not be-- able to unmask exceptions again. If you are writing library code and need-- to use asynchronous exceptions, the only way is to create a new thread;-- see 'Control.Concurrent.forkIOWithUnmask'.---- Asynchronous exceptions may still be received while in the masked-- state if the masked thread /blocks/ in certain ways; see-- "Control.Exception#interruptible".---- Threads created by 'Control.Concurrent.forkIO' inherit the-- 'MaskingState' from the parent; that is, to start a thread in the-- 'MaskedInterruptible' state,-- use @mask_ $ forkIO ...@. This is particularly useful if you need-- to establish an exception handler in the forked thread before any-- asynchronous exceptions are received. To create a new thread in-- an unmasked state use 'Control.Concurrent.forkIOWithUnmask'.--mask::((foralla .IOa ->IOa )->IOb )->IOb -- | Like 'mask', but does not pass a @restore@ action to the argument.mask_::IOa ->IOa -- | Like 'mask', but the masked computation is not interruptible (see-- "Control.Exception#interruptible"). THIS SHOULD BE USED WITH-- GREAT CARE, because if a thread executing in 'uninterruptibleMask'-- blocks for any reason, then the thread (and possibly the program,-- if this is the main thread) will be unresponsive and unkillable.-- This function should only be necessary if you need to mask-- exceptions around an interruptible operation, and you can guarantee-- that the interruptible operation will only block for a short period-- of time.--uninterruptibleMask::((foralla .IOa ->IOa )->IOb )->IOb -- | Like 'uninterruptibleMask', but does not pass a @restore@ action-- to the argument.uninterruptibleMask_::IOa ->IOa mask_ io =mask $ \_->io mask io =dob <-getMaskingState caseb ofUnmasked ->block $ io unblock MaskedInterruptible ->io block MaskedUninterruptible ->io blockUninterruptible uninterruptibleMask_ io =uninterruptibleMask $ \_->io uninterruptibleMask io =dob <-getMaskingState caseb ofUnmasked ->blockUninterruptible $ io unblock MaskedInterruptible ->blockUninterruptible $ io block MaskedUninterruptible ->io blockUninterruptible bracket::IOa -- ^ computation to run first (\"acquire resource\")->(a ->IOb )-- ^ computation to run last (\"release resource\")->(a ->IOc )-- ^ computation to run in-between->IOc -- returns the value from the in-between computationbracket before after thing =mask $ \restore ->doa <-before r <-restore (thing a )`onException `after a _<-after a return r finally::IOa -- ^ computation to run first->IOb -- ^ computation to run afterward (even if an exception-- was raised)->IOa -- returns the value from the first computationa `finally `sequel =mask $ \restore ->dor <-restore a `onException `sequel _<-sequel return r -- | Evaluate the argument to weak head normal form.---- 'evaluate' is typically used to uncover any exceptions that a lazy value-- may contain, and possibly handle them.---- 'evaluate' only evaluates to /weak head normal form/. If deeper-- evaluation is needed, the @force@ function from @Control.DeepSeq@-- may be handy:---- > evaluate $ force x---- There is a subtle difference between @'evaluate' x@ and @'return' '$!' x@,-- analogous to the difference between 'throwIO' and 'throw'. If the lazy-- value @x@ throws an exception, @'return' '$!' x@ will fail to return an-- 'IO' action and will throw an exception instead. @'evaluate' x@, on the-- other hand, always produces an 'IO' action; that action will throw an-- exception upon /execution/ iff @x@ throws an exception upon /evaluation/.---- The practical implication of this difference is that due to the-- /imprecise exceptions/ semantics,---- > (return $! error "foo") >> error "bar"---- may throw either @"foo"@ or @"bar"@, depending on the optimizations-- performed by the compiler. On the other hand,---- > evaluate (error "foo") >> error "bar"---- is guaranteed to throw @"foo"@.---- The rule of thumb is to use 'evaluate' to force or handle exceptions in-- lazy values. If, on the other hand, you are forcing a lazy value for-- efficiency reasons only and do not care about exceptions, you may-- use @'return' '$!' x@.evaluate::a ->IOa evaluate a =IO$ \s ->seq#a s -- NB. see #2273, #5129{- $exceptions_and_strictness
Laziness can interact with @catch@-like operations in non-obvious ways (see,
e.g. GHC Trac #11555 and #13330). For instance, consider these subtly-different
examples:
> test1 = Control.Exception.catch (error "uh oh") (\(_ :: SomeException) -> putStrLn "it failed")
>
> test2 = GHC.IO.catchException (error "uh oh") (\(_ :: SomeException) -> putStrLn "it failed")
While @test1@ will print "it failed", @test2@ will print "uh oh".
When using 'catchException', exceptions thrown while evaluating the
action-to-be-executed will not be caught; only exceptions thrown during
execution of the action will be handled by the exception handler.
Since this strictness is a small optimization and may lead to surprising
results, all of the @catch@ and @handle@ variants offered by "Control.Exception"
use 'catch' rather than 'catchException'.
-}

AltStyle によって変換されたページ (->オリジナル) /