Movatterモバイル変換
[0]ホーム
{-# 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.BaseimportGHC.STimportGHC.ExceptionimportGHC.ShowimportGHC.IO.Unsafeimport{-# SOURCE#-}GHC.IO.Exception(userError,IOError)-- ----------------------------------------------------------------------------- The IO Monad{-The IO Monad is just an instance of the ST monad, where the state isthe real world. We use the exception mechanism (in GHC.Exception) toimplement IO exceptions.NOTE: The IO representation is deeply wired in to various parts of thesystem. The following list may or may not be exhaustive:Compiler - types of various primitives in PrimOp.hsRTS - 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->STretRealWorldaliftIO(IOm)=\s->casemsof(#s',r#)->STrets'rfailIO::String->IOafailIOs=IO(raiseIO#(toException(userErrors)))-- ----------------------------------------------------------------------------- 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::STRealWorlda->IOastToIO(STm)=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->STRealWorldaioToST(IOm)=(STm)-- | 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->STsaunsafeIOToST(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::STsa->IOaunsafeSTToIO(STm)=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 theaction and the handler. This turned out to be a bad idea - it meantthat we had to wrap both arguments in thunks so they could be enteredas 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 wehave 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::Exceptione=>IOa->(e->IOa)->IOacatchException!iohandler=catchiohandler-- | 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::Exceptione=>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#iohandler'wherehandler'e=casefromExceptioneofJuste'->unIO(handlere')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.Exceptione=>e->IOa)->IOacatchAny!(IOio)handler=IO$catch#iohandler'wherehandler'(SomeExceptione)=unIO(handlere)-- 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->IOamplusIOmn=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::Exceptione=>e->IOathrowIOe=IO(raiseIO#(toExceptione))-- ------------------------------------------------------------------------------- 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->IOablock(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->IOaunblock=unsafeUnmaskunsafeUnmask::IOa->IOaunsafeUnmask(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->IOainterruptibleact=dost<-getMaskingStatecasestofUnmasked->actMaskedInterruptible->unsafeUnmaskactMaskedUninterruptible->actblockUninterruptible::IOa->IOablockUninterruptible(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::IOMaskingStategetMaskingState=IO$\s->casegetMaskingState#sof(#s',i#)->(#s',caseiof0#->Unmasked1#->MaskedUninterruptible_->MaskedInterruptible#)onException::IOa->IOb->IOaonExceptioniowhat=io`catchException`\e->do_<-whatthrowIO(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->IOamask_io=mask$\_->iomaskio=dob<-getMaskingStatecasebofUnmasked->block$iounblockMaskedInterruptible->ioblockMaskedUninterruptible->ioblockUninterruptibleuninterruptibleMask_io=uninterruptibleMask$\_->iouninterruptibleMaskio=dob<-getMaskingStatecasebofUnmasked->blockUninterruptible$iounblockMaskedInterruptible->blockUninterruptible$ioblockMaskedUninterruptible->ioblockUninterruptiblebracket::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 computationbracketbeforeafterthing=mask$\restore->doa<-beforer<-restore(thinga)`onException`aftera_<-afterareturnrfinally::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<-restorea`onException`sequel_<-sequelreturnr-- | 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->IOaevaluatea=IO$\s->seq#as-- NB. see #2273, #5129{- $exceptions_and_strictnessLaziness can interact with @catch@-like operations in non-obvious ways (see,e.g. GHC Trac #11555 and #13330). For instance, consider these subtly-differentexamples:> 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 theaction-to-be-executed will not be caught; only exceptions thrown duringexecution of the action will be handled by the exception handler.Since this strictness is a small optimization and may lead to surprisingresults, all of the @catch@ and @handle@ variants offered by "Control.Exception"use 'catch' rather than 'catchException'.-}
[8]ページ先頭