X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FIO.hs;h=8a2dd595b3b8b5e1bf814118163868d79ba57a5a;hb=08cc1c4f54b482dffaef1a1b43c5e0208894f643;hp=fef57dafda62854795263f72365292fe9c6b257e;hpb=d2063b5b0be014545b21819172c87756efcb0b0c;p=ghc-base.git diff --git a/GHC/IO.hs b/GHC/IO.hs index fef57da..8a2dd59 100644 --- a/GHC/IO.hs +++ b/GHC/IO.hs @@ -1,4 +1,4 @@ -{-# OPTIONS_GHC -fno-implicit-prelude -funbox-strict-fields #-} +{-# OPTIONS_GHC -XNoImplicitPrelude -funbox-strict-fields -XBangPatterns #-} {-# OPTIONS_HADDOCK hide #-} ----------------------------------------------------------------------------- -- | @@ -16,7 +16,7 @@ -- #hide module GHC.IO ( - IO(..), unIO, failIO, liftIO, bindIO, thenIO, returnIO, + IO(..), unIO, failIO, liftIO, unsafePerformIO, unsafeInterleaveIO, unsafeDupablePerformIO, unsafeDupableInterleaveIO, noDuplicate, @@ -64,55 +64,9 @@ Libraries - parts of hslibs/lang. --SDM -} -{-| -A value of type @'IO' a@ is a computation which, when performed, -does some I\/O before returning a value of type @a@. - -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. --} -newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #)) - -unIO :: IO a -> (State# RealWorld -> (# State# RealWorld, a #)) -unIO (IO a) = a - -instance Functor IO where - fmap f x = x >>= (return . f) - -instance Monad IO where - {-# INLINE return #-} - {-# INLINE (>>) #-} - {-# INLINE (>>=) #-} - m >> k = m >>= \ _ -> k - return x = returnIO x - - m >>= k = bindIO m k - fail s = failIO s - liftIO :: IO a -> State# RealWorld -> STret RealWorld a liftIO (IO m) = \s -> case m s of (# s', r #) -> STret s' r -bindIO :: IO a -> (a -> IO b) -> IO b -bindIO (IO m) k = IO ( \ s -> - case m s of - (# new_s, a #) -> unIO (k a) new_s - ) - -thenIO :: IO a -> IO b -> IO b -thenIO (IO m) k = IO ( \ s -> - case m s of - (# new_s, _ #) -> unIO k new_s - ) - -returnIO :: a -> IO a -returnIO x = IO (\ s -> (# s, x #)) - failIO :: String -> IO a failIO s = IO (raiseIO# (toException (userError s))) @@ -147,11 +101,15 @@ This is the \"back door\" into the 'IO' monad, allowing this to be safe, the 'IO' computation should be free of side effects and independent of its environment. -If the I\/O computation wrapped in 'unsafePerformIO' -performs side effects, then the relative order in which those side -effects take place (relative to the main I\/O trunk, or other calls to -'unsafePerformIO') is indeterminate. You have to be careful when -writing and compiling modules that use 'unsafePerformIO': +If the I\/O computation wrapped in 'unsafePerformIO' performs side +effects, then the relative order in which those side effects take +place (relative to the main I\/O trunk, or other calls to +'unsafePerformIO') is indeterminate. Furthermore, when using +'unsafePerformIO' to cause side-effects, you should take the following +precautions to ensure the side effects are performed as many times as +you expect them to be. Note that these precautions are necessary for +GHC, but may not be sufficient, and other compilers may require +different precautions: * Use @{\-\# NOINLINE foo \#-\}@ as a pragma on any function @foo@ that calls 'unsafePerformIO'. If the call is inlined, @@ -162,7 +120,7 @@ writing and compiling modules that use 'unsafePerformIO': two side effects that were meant to be separate. A good example is using multiple global variables (like @test@ in the example below). - * Make sure that the either you switch off let-floating, or that the + * Make sure that the either you switch off let-floating (@-fno-full-laziness@), or that the call to 'unsafePerformIO' cannot float outside a lambda. For example, if you say: @ @@ -352,7 +310,7 @@ blocked = IO $ \s -> case asyncExceptionsBlocked# s of (# s', i #) -> (# s', i /=# 0# #) onException :: IO a -> IO b -> IO a -onException io what = io `catchException` \e -> do what +onException io what = io `catchException` \e -> do _ <- what throw (e :: SomeException) finally :: IO a -- ^ computation to run first @@ -362,7 +320,7 @@ finally :: IO a -- ^ computation to run first a `finally` sequel = block (do r <- unblock a `onException` sequel - sequel + _ <- sequel return r ) @@ -381,7 +339,4 @@ a `finally` sequel = -- > evaluate x = (return $! x) >>= return -- evaluate :: a -> IO a -evaluate a = IO $ \s -> case a `seq` () of () -> (# s, a #) - -- NB. can't write - -- a `seq` (# s, a #) - -- because we can't have an unboxed tuple as a function argument +evaluate a = IO $ \s -> let !va = a in (# s, va #) -- NB. see #2273