packages feed

di-monad 1.2 → 1.3

raw patch · 3 files changed

+49/−21 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Di.Monad: throw :: (MonadDi level path msg m, Exception e) => e -> m a

Files

CHANGELOG.md view
@@ -1,3 +1,16 @@+# Version 1.3++* The `MonadThrow` instance for `DiT` doesn't log exceptions automatically any+  more. This is because otherwise catching and re-throwing exceptions in+  downstream code, by default, ends up logging the same exception more than+  once.++* A `throw` function behaving as the previous `MonadThrow` instance for `DiT`+  was introduced.++* Documentation improvements.++ # Version 1.2  * The `MonadMask` constraint added in Version 1.1 is gone, effecively
di-monad.cabal view
@@ -1,5 +1,5 @@ name: di-monad-version: 1.2+version: 1.3 author: Renzo Carbonara maintainer: renλren.zone copyright: Renzo Carbonara 2017-2018
lib/Di/Monad.hs view
@@ -47,6 +47,7 @@  , flush  , push  , filter+ , throw  , onException   , -- * DiT@@ -237,7 +238,7 @@ {-# INLINE runDiT' #-}  -- | Lift a monad morphism from @m@ to @n@ to a monad morphism from--- @'DiT' level path msg m@ to @'DiT' n@.+-- @'DiT' level path msg m@ to @'DiT' level path msg n@. -- -- Notice that 'DiT' itself is not a functor in the category of monads, -- so it can't be an instance of 'Control.Monad.Morph.MFunctor' from the@@ -321,15 +322,11 @@     DiT (ReaderT (\di -> Reader.local f (gma di)))   {-# INLINE local #-} --- | Throw an 'Ex.Exception', but not without logging it first according to the--- rules established by 'onException', and further restricted by the rules--- established by 'filter'.+-- | Throw an 'Ex.Exception' from the underlying @m@, without logging it. ----- WARNING: Note that when `m` is `STM`, or ultimately runs on 'STM', then--- 'Ex.throwM' *will not log* the exception, just throw it. This might change in--- the future if we figure out how to make it work safely.+-- If you want to log the 'Ex.Exception' as you throw it, use 'throw' instead. instance Ex.MonadThrow m => Ex.MonadThrow (DiT level path msg m) where-  throwM e = ask >>= \di -> Di.throw' natSTM di e+  throwM e = DiT (ReaderT (\_ -> Ex.throwM e))   {-# INLINE throwM #-}  instance Ex.MonadCatch m => Ex.MonadCatch (DiT level path msg m) where@@ -516,15 +513,15 @@ -- time when this 'log' function was called, rather than the time when the log -- message is printed in the future. ----- /Note regarding exceptions:/ Any exception thrown by 'natSTM' will be--- thrown here. /Synchronous/ exceptions that happen due to failures in the--- actual committing of the log message are handled by attempting to log the--- message to 'IO.stderr' as a fallback if possible. /Asynchronous/ exceptions--- happening as part of the committing process will be thrown in a different--- thread, and are not not explicitly handled. /Pure/ exceptions originating--- from the 'filter' function will be thrown here. In practical terms, this--- means that unless you know what you are doing, you should just call 'log''--- without worrying about it ever throwing exceptions.+-- /Note regarding exceptions:/ Any exception thrown by 'natSTM' will be thrown+-- here. /Synchronous/ exceptions that happen due to failures in the actual+-- committing of the log message, which itself is performed in a different+-- thread, are ignored (they should be handled in the function passed to 'new'+-- instead). If an asynchronous exception kills the logging thread, then you+-- will synchronously get 'Di.ExceptionInLoggingWorker' here, but by the time+-- that happens, that same exception will have already already been thrown+-- asynchronously to this same thread anyway, so unless you did something funny+-- to recover from that exception, you will have died already. log :: MonadDi level path msg m => level -> msg -> m () log l = \m -> ask >>= \di -> Di.log' natSTM di l m {-# INLINE log #-}@@ -537,6 +534,9 @@ -- asynchronously, meaning there might be log messages still waiting to be -- processed. A call to 'flush' will block until all pending log messages have -- been processed.+--+-- Please see 'log' to understand how exceptions behave in this function (hint:+-- they behave unsurprisingly). flush :: MonadDi level path msg m => m () flush = Di.flush' natSTM =<< ask {-# INLINABLE flush #-}@@ -583,9 +583,9 @@ push p = local (Di.push p) {-# INLINE push #-} --- | Within the passed given @m a@, exceptions thrown with 'Ex.throwM' could--- could be logged as a @msg@ with a particular @level@ if both the passed in--- function returns 'Just', and 'filter' so allows it afterwards.+-- | Within the passed given @m a@, exceptions thrown with 'throw' could could+-- be logged as a @msg@ with a particular @level@ if both the passed in function+-- returns 'Just', and 'filter' so allows it afterwards. -- -- If the given function returns 'Nothing', then no logging is performed. --@@ -609,4 +609,19 @@   -> m a   -> m a onException f = local (Di.onException f)++-- | Throw an 'Ex.Exception', but not without logging it first according to the+-- rules established by 'onException', and further restricted by the rules+-- established by 'filter'.+--+-- If the exception doesn't need to be logged, according to the policy set with+-- 'onException', then this function behaves just as+-- 'Control.Concurrent.STM.throwSTM'.+--+-- WARNING: Note that when `m` is `STM`, or ultimately runs on 'STM', then+-- 'throw' /will not log/ the exception, just throw it. This might change in+-- the future if we figure out how to make it work safely.+throw :: (MonadDi level path msg m, Ex.Exception e) => e -> m a+throw e = ask >>= \di -> Di.throw' natSTM di e+{-# INLINE throw #-}