Hoogle Search
Within LTS Haskell 24.4 (ghc-9.10.2)
Note that Stackage only displays results for the latest LTS and Nightly snapshot. Learn more.
BracketMatchTypeNotFound :: BracketMatchTypegi-gtksource5 GI.GtkSource.Enums a matching bracket was not found.
BracketMatchTypeOutOfRange :: BracketMatchTypegi-gtksource5 GI.GtkSource.Enums matching a bracket failed because the maximum range was reached.
-
haskell-src-exts-util Language.Haskell.Exts.Util No documentation available.
-
aeson Data.Aeson.Encoding.Internal No documentation available.
-
aeson Data.Aeson.Encoding.Internal No documentation available.
-
template-haskell Language.Haskell.TH [|| e ||]
typedBracketE :: Quote m => m Exp -> m Exptemplate-haskell Language.Haskell.TH.Lib No documentation available.
typedBracketE :: Quote m => m Exp -> m Exptemplate-haskell Language.Haskell.TH.Lib.Internal No documentation available.
-
template-haskell Language.Haskell.TH.Syntax [|| e ||]
-
exceptions Control.Monad.Catch A generalized version of bracket which uses ExitCase to distinguish the different exit cases, and returns the values of both the use and release actions. In practice, this extra information is rarely needed, so it is often more convenient to use one of the simpler functions which are defined in terms of this one, such as bracket, finally, onError, and bracketOnError. This function exists because in order to thread their effects through the execution of bracket, monad transformers need values to be threaded from use to release and from release to the output value. NOTE This method was added in version 0.9.0 of this library. Previously, implementation of functions like bracket and finally in this module were based on the mask and uninterruptibleMask functions only, disallowing some classes of tranformers from having MonadMask instances (notably multi-exit-point transformers like ExceptT). If you are a library author, you'll now need to provide an implementation for this method. The StateT implementation demonstrates most of the subtleties:
generalBracket acquire release use = StateT $ \s0 -> do ((b, _s2), (c, s3)) <- generalBracket (runStateT acquire s0) (\(resource, s1) exitCase -> case exitCase of ExitCaseSuccess (b, s2) -> runStateT (release resource (ExitCaseSuccess b)) s2 -- In the two other cases, the base monad overrides `use`'s state -- changes and the state reverts to `s1`. ExitCaseException e -> runStateT (release resource (ExitCaseException e)) s1 ExitCaseAbort -> runStateT (release resource ExitCaseAbort) s1 ) (\(resource, s1) -> runStateT (use resource) s1) return ((b, c), s3)
The StateT s m implementation of generalBracket delegates to the m implementation of generalBracket. The acquire, use, and release arguments given to StateT's implementation produce actions of type StateT s m a, StateT s m b, and StateT s m c. In order to run those actions in the base monad, we need to call runStateT, from which we obtain actions of type m (a, s), m (b, s), and m (c, s). Since each action produces the next state, it is important to feed the state produced by the previous action to the next action. In the ExitCaseSuccess case, the state starts at s0, flows through acquire to become s1, flows through use to become s2, and finally flows through release to become s3. In the other two cases, release does not receive the value s2, so its action cannot see the state changes performed by use. This is fine, because in those two cases, an error was thrown in the base monad, so as per the usual interaction between effects in a monad transformer stack, those state changes get reverted. So we start from s1 instead. Finally, the m implementation of generalBracket returns the pairs (b, s) and (c, s). For monad transformers other than StateT, this will be some other type representing the effects and values performed and returned by the use and release actions. The effect part of the use result, in this case _s2, usually needs to be discarded, since those effects have already been incorporated in the release action. The only effect which is intentionally not incorporated in the release action is the effect of throwing an error. In that case, the error must be re-thrown. One subtlety which is easy to miss is that in the case in which use and release both throw an error, the error from release should take priority. Here is an implementation for ExceptT which demonstrates how to do this.generalBracket acquire release use = ExceptT $ do (eb, ec) <- generalBracket (runExceptT acquire) (\eresource exitCase -> case eresource of Left e -> return (Left e) -- nothing to release, `acquire` didn't succeed Right resource -> case exitCase of ExitCaseSuccess (Right b) -> runExceptT (release resource (ExitCaseSuccess b)) ExitCaseException e -> runExceptT (release resource (ExitCaseException e)) _ -> runExceptT (release resource ExitCaseAbort)) (either (return . Left) (runExceptT . use)) return $ do -- The order in which we perform those two `Either` effects determines -- which error will win if they are both `Left`s. We want the error from -- `release` to win. c <- ec b <- eb return (b, c)