Reputation: 216
I have been taken aback by some peculiar behavior while using the exceptions
package.
I have a function that looks like:
testme ::(MonadThrow m , Monad O m, Applicative m) => FilePath -> Text -> m ()
testme fp t = testfoo fp t >> testbar fp t
with
testfoo :: (MonadThrow m , MonadIO m, Applicative m) => FilePath -> Text -> m ()
testbar :: (MonadThrow m , MonadIO m, Applicative m) => FilePath -> Text -> m ()
Another module will catch all the specific exceptions thrown here doing something along the line:
catching _PrettyError
(do {testCatalog workingdir c; return stm})
(return . S.Left)
And _PrettyError is defined as such:
_PrettyError :: Prism' SomeException PrettyError
_PrettyError = prism' toException fromException
My first surprise comes from the fact that if I change testme
for:
testme = testfoo >> testbar
Ghc refuses to compile because it can't deduce MonadThrow.
Trying this signature:
testme :: FilePath -> Text -> IO ()
testme = testfoo >> testbar
Ghc still don't want to deduce MonadThrow
which I find more surprising.
I am now making another type signature change:
testfoo :: FilePath -> Text -> IO ()
testbar :: FilePath -> Text -> IO ()
And ... it does compile but in utter bewilderment I have then realized that only the exceptions from the second call (testbar) would be caught by catching
.
The ones throws by testfoo
are just lost somehow ...
I am amazed that changing signatures would completely change the exception handling.
The commit of the real code is here (with notes).
The current code does work as expected.
My question is really why the signature change from explicit constraints to a specific IO monad causes such an unexpected behavior (the exceptions from the first term of >>
aren't caught anymore). My understanding is that in both case the IO
monad is at play.
Thanks for your help.
Upvotes: 1
Views: 59
Reputation: 153102
You probably meant testme fp t = testfoo fp t >> testbar fp t
instead of testme = testfoo >> testbar
. In the latter, the (>>)
is from the (->) r
instance, which is what's surprising you: f >> g
is the same as just g
for the (->) r
monad (but makes your computer a little hotter).
Upvotes: 5