Network.firstSuccesful: 'throw' vs 'throwIO' usage

Simon Marlow marlowsd at gmail.com
Thu Sep 6 13:35:52 CEST 2012


On 06/09/2012 11:05, Roman Cheplyaka wrote:
> * Herbert Valerio Riedel <hvr at gnu.org> [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/Network.html#firstSuccessful
>
> 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




More information about the Libraries mailing list