[project @ 2002-12-12 13:42:47 by ross]
authorross <unknown>
Thu, 12 Dec 2002 13:42:47 +0000 (13:42 +0000)
committerross <unknown>
Thu, 12 Dec 2002 13:42:47 +0000 (13:42 +0000)
Changes to the exception interface, as discussed on the libraries list.

1) Move bracket and bracket_ from GHC.Exception (and hence System.IO)
   to haskell98/IO.hs.  These two should now never be used (except in
   all-H98 programs), and this will save users of the new libraries from
   having to hide them.  Use the ones in Control.Exception instead.

2) Define

        type IOError = IOException      -- was Exception

   leaving the type of Prelude.ioError as IOError -> IO a,
   but adding to Control.Exception

        throwIO :: Exception -> IO a

The result is a type distinction between the variants of catch and try:

Prelude.catch           :: IO a -> (IOError -> IO a) -> IO a
Control.Exception.catch :: IO a -> (Exception -> IO a) -> IO a
System.IO.Error.try     :: IO a -> IO (Either IOError a)
Control.Exception.try   :: IO a -> IO (Either Exception a)

These are breaking changes: the first one affects only import lists,
but the second will bite in the following situations:

- using ioError on general Exceptions: use throwIO instead.

- using throw on IOErrors: if in the IO monad, use ioError instead.
  Otherwise, use throw (IOException e), but why are you throwing
  IO exceptions outside of the IO monad?

Minor changes:
- System.IO.Error now exports catch and try
- moved try from GHC.Exception to System.IO.Error, because it's
  portable and can be shared by Hugs.

IO.hs

diff --git a/IO.hs b/IO.hs
index fb0f083..fc299a5 100644 (file)
--- a/IO.hs
+++ b/IO.hs
@@ -23,3 +23,35 @@ module IO (
   ) where
 
 import System.IO
+
+-- | The 'bracket' function captures a common allocate, compute, deallocate
+-- idiom in which the deallocation step must occur even in the case of an
+-- error during computation. This is similar to try-catch-finally in Java.
+--
+-- This version handles only IO errors, as defined by Haskell 98.
+-- The version of @bracket@ in "Control.Exception" handles all exceptions,
+-- and should be used instead.
+
+bracket        :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+bracket before after m = do
+        x  <- before
+        rs <- try (m x)
+        after x
+        case rs of
+           Right r -> return r
+           Left  e -> ioError e
+
+-- | A variant of 'bracket' where the middle computation doesn't want @x@.
+--
+-- This version handles only IO errors, as defined by Haskell 98.
+-- The version of @bracket_@ in "Control.Exception" handles all exceptions,
+-- and should be used instead.
+
+bracket_        :: IO a -> (a -> IO b) -> IO c -> IO c
+bracket_ before after m = do
+         x  <- before
+         rs <- try m
+         after x
+         case rs of
+            Right r -> return r
+            Left  e -> ioError e