@@ -522,7 +522,7 @@ repeatM = Unfold step return
522 step x = x >>= \x1 -> return $ Yield x1 x
522 step x = x >>= \x1 -> return $ Yield x1 x
524-- | Generates an infinite stream starting with the given seed and applying the
524-- | Generates an infinite stream starting with the given seed and applying the
525−-- given function repeteadly.
525+-- given function repeatedly.
527-- /Internal/
527-- /Internal/
@@ -1027,7 +1027,7 @@ apDiscardSnd (Unfold _step1 _inject1) (Unfold _step2 _inject2) = undefined
1027data ConcatMapState s1 s2 = ConcatMapOuter s1 | ConcatMapInner s1 s2
1027data ConcatMapState s1 s2 = ConcatMapOuter s1 | ConcatMapInner s1 s2
1029-- | Map an unfold generating action to each element of an unfold and
1029-- | Map an unfold generating action to each element of an unfold and
1030−-- flattern the results into a single stream.
1030+-- flatten the results into a single stream.
1032{-# INLINE_NORMAL concatMapM #-}
1032{-# INLINE_NORMAL concatMapM #-}
1033concatMapM :: Monad m
1033concatMapM :: Monad m
@@ -1061,9 +1061,14 @@ concatMapM f (Unfold step1 inject1) = Unfold step inject
1061-- Exceptions
1061-- Exceptions
1062------------------------------------------------------------------------------
1062------------------------------------------------------------------------------
1064−-- | The most general bracketing and exception combinator. All other
1064+-- | Like 'gbracket' but with following differences:
1065−-- combinators can be expressed in terms of this combinator. This can also be
1065+--
1066−-- used for cases which are not covered by the standard combinators.
1066+-- * alloc action @a -> m c@ runs with async exceptions enabled
1067+-- * cleanup action @c -> m d@ won't run if the stream is garbage collected
1068+-- after partial evaluation.
1069+-- * does not require a 'MonadAsync' constraint.
1071+-- /Inhibits stream fusion/
1068-- /Internal/
1073-- /Internal/
@@ -1094,6 +1099,7 @@ gbracket_ bef exc aft (Unfold estep einject) (Unfold step1 inject1) =
1094 Yield x s -> return $ Yield x (Right (s, v))
1099 Yield x s -> return $ Yield x (Right (s, v))
1095 Skip s -> return $ Skip (Right (s, v))
1100 Skip s -> return $ Skip (Right (s, v))
1096 Stop -> aft v >> return Stop
1101 Stop -> aft v >> return Stop
1102+ -- XXX Do not handle async exceptions, just rethrow them.
1097 Left e -> do
1103 Left e -> do
1098 r <- einject (v, e)
1104 r <- einject (v, e)
1099 return $ Skip (Left r)
1105 return $ Skip (Left r)
@@ -1104,12 +1110,22 @@ gbracket_ bef exc aft (Unfold estep einject) (Unfold step1 inject1) =
1104 Skip s -> return $ Skip (Left s)
1110 Skip s -> return $ Skip (Left s)
1105 Stop -> return Stop
1111 Stop -> return Stop
1107−-- | The most general bracketing and exception combinator. All other
1113+-- | Run the alloc action @a -> m c@ with async exceptions disabled but keeping
1108−-- combinators can be expressed in terms of this combinator. This can also be
1114+-- blocking operations interruptible (see 'Control.Exception.mask'). Use the
1109−-- used for cases which are not covered by the standard combinators.
1115+-- output @c@ as input to @Unfold m c b@ to generate an output stream. When
1116+-- unfolding use the supplied @try@ operation @forall s. m s -> m (Either e s)@
1117+-- to catch synchronous exceptions. If an exception occurs run the exception
1118+-- handling unfold @Unfold m (c, e) b@.
1111−-- /Internal/
1120+-- The cleanup action @c -> m d@, runs whenever the stream ends normally, due
1121+-- to a sync or async exception or if it gets garbage collected after a partial
1122+-- lazy evaluation. See 'bracket' for the semantics of the cleanup action.
1124+-- 'gbracket' can express all other exception handling combinators.
1126+-- /Inhibits stream fusion/
1113{-# INLINE_NORMAL gbracket #-}
1129{-# INLINE_NORMAL gbracket #-}
1115 :: (MonadIO m, MonadBaseControl IO m)
1131 :: (MonadIO m, MonadBaseControl IO m)
@@ -1144,6 +1160,7 @@ gbracket bef exc aft (Unfold estep einject) (Unfold step1 inject1) =
1144 Stop -> do
1160 Stop -> do
1145 D.runIORefFinalizer ref
1161 D.runIORefFinalizer ref
1146 return Stop
1162 return Stop
1163+ -- XXX Do not handle async exceptions, just rethrow them.
1147 Left e -> do
1164 Left e -> do
1148 -- Clearing of finalizer and running of exception handler must
1165 -- Clearing of finalizer and running of exception handler must
1149 -- be atomic wrt async exceptions. Otherwise if we have cleared
1166 -- be atomic wrt async exceptions. Otherwise if we have cleared
@@ -1167,7 +1184,8 @@ _before :: Monad m => (a -> m c) -> Unfold m a b -> Unfold m a b
1167_before action = gbracket_ (\x -> action x >> return x) (fmap Right)
1184_before action = gbracket_ (\x -> action x >> return x) (fmap Right)
1168 (\_ -> return ()) undefined
1185 (\_ -> return ()) undefined
1170−-- | Run a side effect before the unfold yields its first element.
1187+-- | Run a side effect @a -> m c@ on the input @a@ before unfolding it using
1172-- /Internal/
1190-- /Internal/
1173{-# INLINE_NORMAL before #-}
1191{-# INLINE_NORMAL before #-}
@@ -1192,11 +1210,11 @@ before action (Unfold step1 inject1) = Unfold step inject
1192_after :: Monad m => (a -> m c) -> Unfold m a b -> Unfold m a b
1210_after :: Monad m => (a -> m c) -> Unfold m a b -> Unfold m a b
1193_after aft = gbracket_ return (fmap Right) aft undefined
1211_after aft = gbracket_ return (fmap Right) aft undefined
1195−-- | Run a side effect whenever the unfold stops normally.
1213+-- | Like 'after' with following differences:
1197−-- Prefer 'after' over this as the @after@ action in this combinator is not
1215+-- * action @a -> m c@ won't run if the stream is garbage collected
1198−-- executed if the unfold is partially evaluated lazily and then garbage
1216+-- after partial evaluation.
1199−-- collected.
1217+-- * Monad @m@ does not require any other constraints.
1201-- /Internal/
1219-- /Internal/
1202{-# INLINE_NORMAL after_ #-}
1220{-# INLINE_NORMAL after_ #-}
@@ -1217,8 +1235,14 @@ after_ action (Unfold step1 inject1) = Unfold step inject
1217 Skip s -> return $ Skip (s, v)
1235 Skip s -> return $ Skip (s, v)
1218 Stop -> action v >> return Stop
1236 Stop -> action v >> return Stop
1220−-- | Run a side effect whenever the unfold stops normally
1238+-- | Unfold the input @a@ using @Unfold m a b@, run an action on @a@ whenever
1221−-- or is garbage collected after a partial lazy evaluation.
1239+-- the unfold stops normally, or if it is garbage collected after a partial
1242+-- The semantics of the action @a -> m c@ are similar to the cleanup action
1243+-- semantics in 'bracket'.
1245+-- /See also 'after_'/
1223-- /Internal/
1247-- /Internal/
1224{-# INLINE_NORMAL after #-}
1248{-# INLINE_NORMAL after #-}
@@ -1250,7 +1274,10 @@ _onException action =
1250 (\_ -> return ())
1274 (\_ -> return ())
1251 (nilM (\(a, e :: MC.SomeException) -> action a >> MC.throwM e))
1275 (nilM (\(a, e :: MC.SomeException) -> action a >> MC.throwM e))
1277+-- | Unfold the input @a@ using @Unfold m a b@, run the action @a -> m c@ on
1253−-- | Run a side effect whenever the unfold aborts due to an exception.
1278+-- @a@ if the unfold aborts due to an exception.
1280+-- /Inhibits stream fusion/
1255-- /Internal/
1282-- /Internal/
1256{-# INLINE_NORMAL onException #-}
1283{-# INLINE_NORMAL onException #-}
@@ -1277,12 +1304,13 @@ _finally action =
1277 gbracket_ return MC.try action
1304 gbracket_ return MC.try action
1278 (nilM (\(a, e :: MC.SomeException) -> action a >> MC.throwM e))
1305 (nilM (\(a, e :: MC.SomeException) -> action a >> MC.throwM e))
1280−-- | Run a side effect whenever the unfold stops normally or aborts due to an
1307+-- | Like 'finally' with following differences:
1283−-- Prefer 'finally' over this as the @after@ action in this combinator is not
1309+-- * action @a -> m c@ won't run if the stream is garbage collected
1284−-- executed if the unfold is partially evaluated lazily and then garbage
1310+-- after partial evaluation.
1285−-- collected.
1311+-- * does not require a 'MonadAsync' constraint.
1313+-- /Inhibits stream fusion/
1287-- /Internal/
1315-- /Internal/
1288{-# INLINE_NORMAL finally_ #-}
1316{-# INLINE_NORMAL finally_ #-}
@@ -1303,8 +1331,20 @@ finally_ action (Unfold step1 inject1) = Unfold step inject
1303 Skip s -> return $ Skip (s, v)
1331 Skip s -> return $ Skip (s, v)
1304 Stop -> action v >> return Stop
1332 Stop -> action v >> return Stop
1334+-- | Unfold the input @a@ using @Unfold m a b@, run an action on @a@ whenever
1306−-- | Run a side effect whenever the unfold stops normally, aborts due to an
1335+-- the unfold stops normally, aborts due to an exception or if it is garbage
1307−-- exception or if it is garbage collected after a partial lazy evaluation.
1336+-- collected after a partial lazy evaluation.
1338+-- The semantics of the action @a -> m c@ are similar to the cleanup action
1339+-- semantics in 'bracket'.
1342+-- finally release = bracket return release
1345+-- /See also 'finally_'/
1347+-- /Inhibits stream fusion/
1309-- /Internal/
1349-- /Internal/
1310{-# INLINE_NORMAL finally #-}
1350{-# INLINE_NORMAL finally #-}
@@ -1336,14 +1376,14 @@ _bracket bef aft =
1336 gbracket_ bef MC.try aft (nilM (\(a, e :: MC.SomeException) -> aft a >>
1376 gbracket_ bef MC.try aft (nilM (\(a, e :: MC.SomeException) -> aft a >>
1337 MC.throwM e))
1377 MC.throwM e))
1339−-- | @bracket_ before after between@ runs the @before@ action and then unfolds
1379+-- | Like 'bracket' but with following differences:
1340−-- its output using the @between@ unfold. When the @between@ unfold is done or
1380+--
1341−-- if an exception occurs then the @after@ action is run with the output of
1381+-- * alloc action @a -> m c@ runs with async exceptions enabled
1342−-- @before@ as argument.
1382+-- * cleanup action @c -> m d@ won't run if the stream is garbage collected
1383+-- after partial evaluation.
1384+-- * does not require a 'MonadAsync' constraint.
1344−-- Prefer 'bracket' over this as the @after@ action in this combinator is not
1386+-- /Inhibits stream fusion/
1345−-- executed if the unfold is partially evaluated lazily and then garbage
1348-- /Internal/
1388-- /Internal/
1349{-# INLINE_NORMAL bracket_ #-}
1389{-# INLINE_NORMAL bracket_ #-}
@@ -1366,11 +1406,26 @@ bracket_ bef aft (Unfold step1 inject1) = Unfold step inject
1366 Skip s -> return $ Skip (s, v)
1406 Skip s -> return $ Skip (s, v)
1367 Stop -> aft v >> return Stop
1407 Stop -> aft v >> return Stop
1369−-- | @bracket before after between@ runs the @before@ action and then unfolds
1409+-- | Run the alloc action @a -> m c@ with async exceptions disabled but keeping
1370−-- its output using the @between@ unfold. When the @between@ unfold is done or
1410+-- blocking operations interruptible (see 'Control.Exception.mask'). Use the
1371−-- if an exception occurs then the @after@ action is run with the output of
1411+-- output @c@ as input to @Unfold m c b@ to generate an output stream.
1372−-- @before@ as argument. The after action is also executed if the unfold is
1412+--
1373−-- paritally evaluated and then garbage collected.
1413+-- @c@ is usually a resource under the state of monad @m@, e.g. a file
1414+-- handle, that requires a cleanup after use. The cleanup action @c -> m d@,
1415+-- runs whenever the stream ends normally, due to a sync or async exception or
1416+-- if it gets garbage collected after a partial lazy evaluation.
1418+-- 'bracket' only guarantees that the cleanup action runs, and it runs with
1419+-- async exceptions enabled. The action must ensure that it can successfully
1420+-- cleanup the resource in the face of sync or async exceptions.
1422+-- When the stream ends normally or on a sync exception, cleanup action runs
1423+-- immediately in the current thread context, whereas in other cases it runs in
1424+-- the GC context, therefore, cleanup may be delayed until the GC gets to run.
1426+-- /See also: 'bracket_', 'gbracket'/
1428+-- /Inhibits stream fusion/
1375-- /Internal/
1430-- /Internal/
1376{-# INLINE_NORMAL bracket #-}
1431{-# INLINE_NORMAL bracket #-}
@@ -1400,8 +1455,10 @@ bracket bef aft (Unfold step1 inject1) = Unfold step inject
1400 D.runIORefFinalizer ref
1455 D.runIORefFinalizer ref
1401 return Stop
1456 return Stop
1403−-- | When unfolding if an exception occurs, unfold the exception using the
1458+-- | When unfolding @Unfold m a b@ if an exception @e@ occurs, unfold @e@ using
1404−-- exception unfold supplied as the first argument to 'handle'.
1459+-- @Unfold m e b@.
1461+-- /Inhibits stream fusion/
1406-- /Internal/
1463-- /Internal/
1407{-# INLINE_NORMAL handle #-}
1464{-# INLINE_NORMAL handle #-}