elaborate the docs for unsafePerformIO a bit
[ghc-base.git] / GHC / IO.hs
index 865a09c..8a2dd59 100644 (file)
--- a/GHC/IO.hs
+++ b/GHC/IO.hs
@@ -1,5 +1,4 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-# OPTIONS_GHC -fno-implicit-prelude -funbox-strict-fields #-}
+{-# OPTIONS_GHC -XNoImplicitPrelude -funbox-strict-fields -XBangPatterns #-}
 {-# OPTIONS_HADDOCK hide #-}
 -----------------------------------------------------------------------------
 -- |
 {-# OPTIONS_HADDOCK hide #-}
 -----------------------------------------------------------------------------
 -- |
@@ -17,7 +16,7 @@
 
 -- #hide
 module GHC.IO (
 
 -- #hide
 module GHC.IO (
-    IO(..), unIO, failIO, liftIO, bindIO, thenIO, returnIO, 
+    IO(..), unIO, failIO, liftIO,
     unsafePerformIO, unsafeInterleaveIO,
     unsafeDupablePerformIO, unsafeDupableInterleaveIO,
     noDuplicate,
     unsafePerformIO, unsafeInterleaveIO,
     unsafeDupablePerformIO, unsafeDupableInterleaveIO,
     noDuplicate,
@@ -65,40 +64,9 @@ Libraries - parts of hslibs/lang.
 --SDM
 -}
 
 --SDM
 -}
 
-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
 
 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)))
 
 failIO :: String -> IO a
 failIO s = IO (raiseIO# (toException (userError s)))
 
@@ -133,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.
 
 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,
 
   * Use @{\-\# NOINLINE foo \#-\}@ as a pragma on any function @foo@
         that calls 'unsafePerformIO'.  If the call is inlined,
@@ -148,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).
 
         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:
         @
         call to 'unsafePerformIO' cannot float outside a lambda.  For example, 
         if you say:
         @
@@ -338,7 +310,7 @@ blocked = IO $ \s -> case asyncExceptionsBlocked# s of
                         (# s', i #) -> (# s', i /=# 0# #)
 
 onException :: IO a -> IO b -> IO a
                         (# 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
                                                    throw (e :: SomeException)
 
 finally :: IO a         -- ^ computation to run first
@@ -348,7 +320,7 @@ finally :: IO a         -- ^ computation to run first
 a `finally` sequel =
   block (do
     r <- unblock a `onException` sequel
 a `finally` sequel =
   block (do
     r <- unblock a `onException` sequel
-    sequel
+    _ <- sequel
     return r
   )
 
     return r
   )
 
@@ -367,7 +339,4 @@ a `finally` sequel =
 -- >   evaluate x = (return $! x) >>= return
 --
 evaluate :: a -> IO a
 -- >   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