on master help sign in
Show that listen works as advertised
bf25f34Andrzej Rybczak
effectful-core/src/Effectful/State/Local.hs+8−5
@@ -5,13 +5,12 @@
5--
5--
6-- - very fast.
6-- - very fast.
7--
7--
8−-- /Note:/ unlike 'Control.Monad.Trans.State.StateT', the 'State' effect doesn't
8+-- /Note:/ unlike the 'Control.Monad.Trans.State.StateT' monad transformer from
9−-- lose state modifications in presence of runtime exceptions:
9+-- the @transformers@ library, the 'State' effect doesn't lose state
10−--
10+-- modifications when an exception is received:
11−-- >>> import Control.Exception (ErrorCall)
12−-- >>> import Control.Monad.Catch
13--
11--
14-- >>> import qualified Control.Monad.Trans.State.Strict as S
12-- >>> import qualified Control.Monad.Trans.State.Strict as S
13+--
15-- >>> :{
14-- >>> :{
16-- (`S.execStateT` "Hi") . handle (\(_::ErrorCall) -> pure ()) $ do
15-- (`S.execStateT` "Hi") . handle (\(_::ErrorCall) -> pure ()) $ do
17-- S.modify (++ " there!")
16-- S.modify (++ " there!")
@@ -126,3 +125,7 @@ modifyM
126 => (s -> Eff es s) -- ^ The monadic function to modify the state.
125 => (s -> Eff es s) -- ^ The monadic function to modify the state.
127 -> Eff es ()
126 -> Eff es ()
128modifyM f = stateM (\s -> ((), ) <$> f s)
127modifyM f = stateM (\s -> ((), ) <$> f s)
128+
129+-- $setup
130+-- >>> import Control.Exception (ErrorCall)
131+-- >>> import Control.Monad.Catch
effectful-core/src/Effectful/Writer/Local.hs+17−2
@@ -24,7 +24,7 @@ module Effectful.Writer.Local
24 , listens
24 , listens
25 ) where
25 ) where
26
26
27−import Control.Exception
27+import Control.Exception (onException, mask)
28
28
29import Effectful.Dispatch.Static
29import Effectful.Dispatch.Static
30import Effectful.Monad
30import Effectful.Monad
@@ -57,7 +57,18 @@ tell w = stateEffect $ \(IdA (Writer w0)) -> ((), IdA (Writer (w0 <> w)))
57--
57--
58-- /Note:/ if a runtime exception is received while the action is executed, the
58-- /Note:/ if a runtime exception is received while the action is executed, the
59-- partial output of the action will still be appended to the overall output of
59-- partial output of the action will still be appended to the overall output of
60−-- the 'Writer'.
60+-- the 'Writer':
61+--
62+-- >>> :{
63+-- runEff . execWriter @String $ do
64+-- tell "Hi"
65+-- handle (\(_::ErrorCall) -> pure ((), "")) $ do
66+-- tell " there"
67+-- listen $ do
68+-- tell "!"
69+-- error "oops"
70+-- :}
71+-- "Hi there!"
61listen :: (Writer w :> es, Monoid w) => Eff es a -> Eff es (a, w)
72listen :: (Writer w :> es, Monoid w) => Eff es a -> Eff es (a, w)
62listen m = unsafeEff $ \es -> mask $ \restore -> do
73listen m = unsafeEff $ \es -> mask $ \restore -> do
63 w0 <- stateEnv es $ \(IdA (Writer w)) -> (w, IdA (Writer mempty))
74 w0 <- stateEnv es $ \(IdA (Writer w)) -> (w, IdA (Writer mempty))
@@ -77,3 +88,7 @@ listens :: (Writer w :> es, Monoid w) => (w -> b) -> Eff es a -> Eff es (a, b)
77listens f m = do
88listens f m = do
78 (a, w) <- listen m
89 (a, w) <- listen m
79 pure (a, f w)
90 pure (a, f w)
91+
92+-- $setup
93+-- >>> import Control.Monad.Catch
94+-- >>> import Control.Exception (ErrorCall)