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