-
-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
inSpan without UnliftIO #76
Comments
for example, I think this works: bracketErrorIO :: IO a -> (Maybe SomeException -> a -> IO b) -> (a -> IO c) -> IO c
bracketErrorIO before after thing = EUnsafe.mask $ \restore -> do
x <- before
res1 <- EUnsafe.try $ restore $ thing x
case res1 of
Left (e1 :: SomeException) -> do
-- explicitly ignore exceptions from after. We know that
-- no async exceptions were thrown there, so therefore
-- the stronger exception must come from thing
--
-- https://github.com/fpco/safe-exceptions/issues/2
_ :: Either SomeException b <-
EUnsafe.try $ EUnsafe.uninterruptibleMask_ $ after (Just e1) x
EUnsafe.throwIO e1
Right y -> do
_ <- EUnsafe.uninterruptibleMask_ $ after Nothing x
return y |
This is probably a good overview on the tradeoffs around catching errors for various monads:
This is a particularly important principal for observability tooling– the presence of of tracing should not affect the semantics of the code that's being instrumented. Therefore, we go with the most conservative option for what the library supports by default. If you don't particularly care about maintaining those semantics in your situation, you could use the However, there are often ways to make it work for your situation, even with Say you're working with ExceptT, for example: getUser :: MonadIO m => ExceptT HttpResponse m User
getUser = do
thing1 <- foo
thing2 <- bar
thing3 <- baz
pure $ constructUser thing1 thing2 thing3
-- natural transformation
nt :: AppState -> AppM a -> Handler a
nt s x = Handler $ ExceptT $ catch (Right <$> runAppM s x) $ \(e :: ServerError) -> pure $ Left e
|
Oh this is great. I actually ended up implementing exactly the exceptions solution, but I think the natural transformation is the one I want (and I happen to be using servant). |
I do think there's value in providing a |
I am working on an app where the monad doesn't support unliftio. I would like to understand why inSpan requires UnliftIO? It seems like it is just in the
bracketError
function. It would be great to provide an inSpan function that doesn't require this constraint, but I am not sure where to start.The text was updated successfully, but these errors were encountered: