
On 06/09/2012 11:05, Roman Cheplyaka wrote:
* Herbert Valerio Riedel
[2012-09-06 11:40:23+0200] Hello,
while reading over the source code of network[1], I noticed a use of 'throw' where I'd expect 'throwIO':
import qualified Control.Exception as Exception
catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a catchIO = Exception.catch
-- Returns the first action from a list which does not throw an exception. -- If all the actions throw exceptions (and the list of actions is not empty), -- the last exception is thrown. firstSuccessful :: [IO a] -> IO a firstSuccessful [] = error "firstSuccessful: empty list" firstSuccessful (p:ps) = catchIO p $ \e -> case ps of [] -> Exception.throw e _ -> firstSuccessful ps
...so, is `throw` used properly in the code above, or should it rather be `throwIO`?
[1]: http://hackage.haskell.org/packages/archive/network/2.3.1.0/doc/html/src/Net...
In this particular situation it doesn't matter.
If you use throwIO, then, if all actions fail, firstSuccesful will return a proper IO action which, when sequenced, throws an exception.
If you use throw, then in the same situation the result of firstSuccessful will throw an exception before yielding a proper IO value.
However, I agree with you that throwIO would be somewhat more idiomatic here. (And IIRC I wrote this code, so you can blame me.)
Here is some background reading: http://hackage.haskell.org/trac/ghc/ticket/1171 The bottom line is that it's hard to tell what will happen if you use throw here. Always use throwIO if you can. Cheers, Simon