Movatterモバイル変換


[0]ホーム

URL:


{-# LANGUAGE Unsafe #-}{-# LANGUAGE NoImplicitPrelude           , BangPatterns           , RankNTypes           , MagicHash           , ScopedTypeVariables           , UnboxedTuples  #-}{-# OPTIONS_GHC -funbox-strict-fields #-}{-# OPTIONS_HADDOCK not-home #-}------------------------------------------------------------------------------- |-- 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,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,mkUserError)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 threadis the 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 :: IO a -> State# RealWorld -> STret RealWorld aliftIO(IOState# RealWorld -> (# State# RealWorld, a #)m)=\State# RealWorlds->caseState# RealWorld -> (# State# RealWorld, a #)mState# RealWorldsof(#State# RealWorlds',ar#)->State# RealWorld -> a -> STret RealWorld aforall s a. State# s -> a -> STret s aSTretState# RealWorlds'ar-- ----------------------------------------------------------------------------- Coercions between IO and ST-- | Embed a strict state thread 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 :: ST RealWorld a -> IO astToIO(STSTRep RealWorld am)=STRep RealWorld a -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIOSTRep RealWorld am-- | Convert an 'IO' action into an 'ST' action. The type of the result-- is constrained to use a 'RealWorld' state thread, and therefore the-- result cannot be passed to 'runST'.ioToST::IOa->STRealWorldaioToST :: IO a -> ST RealWorld aioToST(IOState# RealWorld -> (# State# RealWorld, a #)m)=((State# RealWorld -> (# State# RealWorld, a #)) -> ST RealWorld aforall s a. STRep s a -> ST s aSTState# RealWorld -> (# State# RealWorld, a #)m)-- | Convert an 'IO' action to an 'ST' action.-- This relies on 'IO' and 'ST' having the same representation modulo the-- constraint on the state thread type parameter.unsafeIOToST::IOa->STsaunsafeIOToST :: IO a -> ST s aunsafeIOToST(IOState# RealWorld -> (# State# RealWorld, a #)io)=STRep s a -> ST s aforall s a. STRep s a -> ST s aST(STRep s a -> ST s a) -> STRep s a -> ST s aforall a b. (a -> b) -> a -> b$\State# ss->((State# RealWorld -> (# State# RealWorld, a #)) -> STRep s aunsafeCoerce#State# RealWorld -> (# State# RealWorld, a #)io)State# ss-- | Convert an 'ST' action to an 'IO' action.-- This relies on 'IO' and 'ST' having the same representation modulo the-- constraint on the state thread type parameter.---- For an example demonstrating why this is unsafe, see-- https://mail.haskell.org/pipermail/haskell-cafe/2009-April/060719.htmlunsafeSTToIO::STsa->IOaunsafeSTToIO :: ST s a -> IO aunsafeSTToIO(STSTRep s am)=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO(STRep s a -> State# RealWorld -> (# State# RealWorld, a #)unsafeCoerce#STRep s am)-- ------------------------------------------------------------------------------- | 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 :: IO a -> (e -> IO a) -> IO acatchException!IO aioe -> IO ahandler=IO a -> (e -> IO a) -> IO aforall e a. Exception e => IO a -> (e -> IO a) -> IO acatchIO aioe -> IO ahandler-- | 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 :: IO a -> (e -> IO a) -> IO acatch(IOState# RealWorld -> (# State# RealWorld, a #)io)e -> IO ahandler=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)-> (State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a b. (a -> b) -> a -> b$(State# RealWorld -> (# State# RealWorld, a #))-> (SomeException -> State# RealWorld -> (# State# RealWorld, a #))-> State# RealWorld-> (# State# RealWorld, a #)forall k1 a.(State# RealWorld -> (# State# RealWorld, k1 #))-> (a -> State# RealWorld -> (# State# RealWorld, k1 #))-> State# RealWorld-> (# State# RealWorld, k1 #)catch#State# RealWorld -> (# State# RealWorld, a #)ioSomeException -> State# RealWorld -> (# State# RealWorld, a #)handler'wherehandler' :: SomeException -> State# RealWorld -> (# State# RealWorld, a #)handler'SomeExceptione=caseSomeException -> Maybe eforall e. Exception e => SomeException -> Maybe efromExceptionSomeExceptioneofJustee'->IO a -> State# RealWorld -> (# State# RealWorld, a #)forall a. IO a -> State# RealWorld -> (# State# RealWorld, a #)unIO(e -> IO ahandleree')Maybe eNothing->SomeException -> State# RealWorld -> (# State# RealWorld, a #)forall k1 a. k1 -> State# RealWorld -> (# State# RealWorld, a #)raiseIO#SomeExceptione-- | 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 :: IO a -> (forall e. Exception e => e -> IO a) -> IO acatchAny!(IOState# RealWorld -> (# State# RealWorld, a #)io)forall e. Exception e => e -> IO ahandler=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)-> (State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a b. (a -> b) -> a -> b$(State# RealWorld -> (# State# RealWorld, a #))-> (SomeException -> State# RealWorld -> (# State# RealWorld, a #))-> State# RealWorld-> (# State# RealWorld, a #)forall k1 a.(State# RealWorld -> (# State# RealWorld, k1 #))-> (a -> State# RealWorld -> (# State# RealWorld, k1 #))-> State# RealWorld-> (# State# RealWorld, k1 #)catch#State# RealWorld -> (# State# RealWorld, a #)ioSomeException -> State# RealWorld -> (# State# RealWorld, a #)handler'wherehandler' :: SomeException -> State# RealWorld -> (# State# RealWorld, a #)handler'(SomeExceptionee)=IO a -> State# RealWorld -> (# State# RealWorld, a #)forall a. IO a -> State# RealWorld -> (# State# RealWorld, a #)unIO(e -> IO aforall e. Exception e => e -> IO ahandleree)-- 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->IOamplusIO :: IO a -> IO a -> IO amplusIOIO amIO an=IO amIO a -> (IOError -> IO a) -> IO aforall e a. Exception e => IO a -> (e -> IO a) -> IO a`catchException`\(IOError_::IOError)->IO an-- | 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->IOathrowIO :: e -> IO athrowIOee=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO(SomeException -> State# RealWorld -> (# State# RealWorld, a #)forall k1 a. k1 -> State# RealWorld -> (# State# RealWorld, a #)raiseIO#(e -> SomeExceptionforall e. Exception e => e -> SomeExceptiontoExceptionee))-- ------------------------------------------------------------------------------- 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 :: IO a -> IO ablock(IOState# RealWorld -> (# State# RealWorld, a #)io)=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)-> (State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a b. (a -> b) -> a -> b$(State# RealWorld -> (# State# RealWorld, a #))-> State# RealWorld -> (# State# RealWorld, a #)forall k1.(State# RealWorld -> (# State# RealWorld, k1 #))-> State# RealWorld -> (# State# RealWorld, k1 #)maskAsyncExceptions#State# RealWorld -> (# State# RealWorld, a #)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 :: IO a -> IO aunblock=IO a -> IO aforall a. IO a -> IO aunsafeUnmaskunsafeUnmask::IOa->IOaunsafeUnmask :: IO a -> IO aunsafeUnmask(IOState# RealWorld -> (# State# RealWorld, a #)io)=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)-> (State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a b. (a -> b) -> a -> b$(State# RealWorld -> (# State# RealWorld, a #))-> State# RealWorld -> (# State# RealWorld, a #)forall k1.(State# RealWorld -> (# State# RealWorld, k1 #))-> State# RealWorld -> (# State# RealWorld, k1 #)unmaskAsyncExceptions#State# RealWorld -> (# State# RealWorld, a #)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->IOainterruptible :: IO a -> IO ainterruptibleIO aact=doMaskingStatest<-IO MaskingStategetMaskingStatecaseMaskingStatestofMaskingStateUnmasked->IO aactMaskingStateMaskedInterruptible->IO a -> IO aforall a. IO a -> IO aunsafeUnmaskIO aactMaskingStateMaskedUninterruptible->IO aactblockUninterruptible::IOa->IOablockUninterruptible :: IO a -> IO ablockUninterruptible(IOState# RealWorld -> (# State# RealWorld, a #)io)=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)-> (State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a b. (a -> b) -> a -> b$(State# RealWorld -> (# State# RealWorld, a #))-> State# RealWorld -> (# State# RealWorld, a #)forall k1.(State# RealWorld -> (# State# RealWorld, k1 #))-> State# RealWorld -> (# State# RealWorld, k1 #)maskUninterruptible#State# RealWorld -> (# State# RealWorld, a #)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 MaskingStategetMaskingState=(State# RealWorld -> (# State# RealWorld, MaskingState #))-> IO MaskingStateforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO((State# RealWorld -> (# State# RealWorld, MaskingState #)) -> IO MaskingState)-> (State# RealWorld -> (# State# RealWorld, MaskingState #))-> IO MaskingStateforall a b. (a -> b) -> a -> b$\State# RealWorlds->caseState# RealWorld -> (# State# RealWorld, Int# #)getMaskingState#State# RealWorldsof(#State# RealWorlds',Int#i#)->(#State# RealWorlds',caseInt#iofInt#0#->MaskingStateUnmaskedInt#1#->MaskingStateMaskedUninterruptibleInt#_->MaskingStateMaskedInterruptible#)onException::IOa->IOb->IOaonException :: IO a -> IO b -> IO aonExceptionIO aioIO bwhat=IO aioIO a -> (SomeException -> IO a) -> IO aforall e a. Exception e => IO a -> (e -> IO a) -> IO a`catchException`\SomeExceptione->dob_<-IO bwhatSomeException -> IO aforall e a. Exception e => e -> IO athrowIO(SomeExceptione::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 a -> IO amask_IO aio=((forall a. IO a -> IO a) -> IO a) -> IO aforall b. ((forall a. IO a -> IO a) -> IO b) -> IO bmask(((forall a. IO a -> IO a) -> IO a) -> IO a)-> ((forall a. IO a -> IO a) -> IO a) -> IO aforall a b. (a -> b) -> a -> b$\forall a. IO a -> IO a_->IO aiomask :: ((forall a. IO a -> IO a) -> IO b) -> IO bmask(forall a. IO a -> IO a) -> IO bio=doMaskingStateb<-IO MaskingStategetMaskingStatecaseMaskingStatebofMaskingStateUnmasked->IO b -> IO bforall a. IO a -> IO ablock(IO b -> IO b) -> IO b -> IO bforall a b. (a -> b) -> a -> b$(forall a. IO a -> IO a) -> IO bioforall a. IO a -> IO aunblockMaskingStateMaskedInterruptible->(forall a. IO a -> IO a) -> IO bioforall a. IO a -> IO ablockMaskingStateMaskedUninterruptible->(forall a. IO a -> IO a) -> IO bioforall a. IO a -> IO ablockUninterruptibleuninterruptibleMask_ :: IO a -> IO auninterruptibleMask_IO aio=((forall a. IO a -> IO a) -> IO a) -> IO aforall b. ((forall a. IO a -> IO a) -> IO b) -> IO buninterruptibleMask(((forall a. IO a -> IO a) -> IO a) -> IO a)-> ((forall a. IO a -> IO a) -> IO a) -> IO aforall a b. (a -> b) -> a -> b$\forall a. IO a -> IO a_->IO aiouninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO buninterruptibleMask(forall a. IO a -> IO a) -> IO bio=doMaskingStateb<-IO MaskingStategetMaskingStatecaseMaskingStatebofMaskingStateUnmasked->IO b -> IO bforall a. IO a -> IO ablockUninterruptible(IO b -> IO b) -> IO b -> IO bforall a b. (a -> b) -> a -> b$(forall a. IO a -> IO a) -> IO bioforall a. IO a -> IO aunblockMaskingStateMaskedInterruptible->IO b -> IO bforall a. IO a -> IO ablockUninterruptible(IO b -> IO b) -> IO b -> IO bforall a b. (a -> b) -> a -> b$(forall a. IO a -> IO a) -> IO bioforall a. IO a -> IO ablockMaskingStateMaskedUninterruptible->(forall a. IO a -> IO a) -> IO bioforall a. IO a -> IO ablockUninterruptiblebracket::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 :: IO a -> (a -> IO b) -> (a -> IO c) -> IO cbracketIO abeforea -> IO baftera -> IO cthing=((forall a. IO a -> IO a) -> IO c) -> IO cforall b. ((forall a. IO a -> IO a) -> IO b) -> IO bmask(((forall a. IO a -> IO a) -> IO c) -> IO c)-> ((forall a. IO a -> IO a) -> IO c) -> IO cforall a b. (a -> b) -> a -> b$\forall a. IO a -> IO arestore->doaa<-IO abeforecr<-IO c -> IO cforall a. IO a -> IO arestore(a -> IO cthingaa)IO c -> IO b -> IO cforall a b. IO a -> IO b -> IO a`onException`a -> IO bafteraab_<-a -> IO bafteraac -> IO cforall (m :: * -> *) a. Monad m => a -> m areturncrfinally::IOa-- ^ computation to run first->IOb-- ^ computation to run afterward (even if an exception-- was raised)->IOa-- returns the value from the first computationIO aafinally :: IO a -> IO b -> IO a`finally`IO bsequel=((forall a. IO a -> IO a) -> IO a) -> IO aforall b. ((forall a. IO a -> IO a) -> IO b) -> IO bmask(((forall a. IO a -> IO a) -> IO a) -> IO a)-> ((forall a. IO a -> IO a) -> IO a) -> IO aforall a b. (a -> b) -> a -> b$\forall a. IO a -> IO arestore->doar<-IO a -> IO aforall a. IO a -> IO arestoreIO aaIO a -> IO b -> IO aforall a b. IO a -> IO b -> IO a`onException`IO bsequelb_<-IO bsequela -> IO aforall (m :: * -> *) a. Monad m => a -> m areturnar-- | 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->IOaevaluate :: a -> IO aevaluateaa=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)-> (State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a b. (a -> b) -> a -> b$\State# RealWorlds->a -> State# RealWorld -> (# State# RealWorld, a #)forall k1 d. k1 -> State# d -> (# State# d, k1 #)seq#aaState# RealWorlds-- NB. see #2273, #5129{- $exceptions_and_strictnessLaziness can interact with @catch@-like operations in non-obvious ways (see,e.g. GHC #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'.-}-- For SOURCE import by GHC.Base to define failIO.mkUserError::[Char]->SomeExceptionmkUserError :: String -> SomeExceptionmkUserErrorStringstr=IOError -> SomeExceptionforall e. Exception e => e -> SomeExceptiontoException(String -> IOErroruserErrorStringstr)

[8]ページ先頭

©2009-2025 Movatter.jp