@@ -0,0 +1,88 @@
1+module Effectful.Writer.Dynamic
2+ ( Writer(..)
3+
4+ -- * Pure
5+ , runWriter
6+ , execWriter
7+
8+ -- * MVar
9+ , runWriterMVar
10+ , execWriterMVar
11+
12+ -- * Operations
13+ , writer
14+ , tell
15+ , listen
16+ , listens
17+ ) where
18+
19+import Effectful.Internal.Effect
20+import Effectful.Internal.Monad
21+import Effectful.Interpreter
22+
23+import qualified Effectful.Writer as WP
24+import qualified Effectful.Writer.MVar as WM
25+
26+data Writer w :: Effect where
27+ Writer :: (a, w) -> Writer w m a
28+ Tell :: ~w -> Writer w m ()
29+ Listen :: m a -> Writer w m (a, w)
30+
31+----------------------------------------
32+-- Pure
33+
34+runWriter :: Monoid w => Eff (Writer w : es) a -> Eff es (a, w)
35+runWriter = reinterpretM WP.runWriter writerPure
36+
37+execWriter :: Monoid w => Eff (Writer w : es) a -> Eff es w
38+execWriter = reinterpretM WP.execWriter writerPure
39+
40+writerPure
41+ :: (Monoid w, WP.Writer w :> localEs)
42+ => RunIn es (Eff localEs)
43+ -> Writer w (Eff es) a
44+ -> Eff localEs a
45+writerPure run = \case
46+ Writer aw -> WP.writer aw
47+ Tell w -> WP.tell w
48+ Listen m -> WP.listen (run m)
49+
50+----------------------------------------
51+-- MVar
52+
53+runWriterMVar :: Monoid w => Eff (Writer w : es) a -> Eff es (a, w)
54+runWriterMVar = reinterpretM WM.runWriter writerMVar
55+
56+execWriterMVar :: Monoid w => Eff (Writer w : es) a -> Eff es w
57+execWriterMVar = reinterpretM WM.execWriter writerMVar
58+
59+writerMVar
60+ :: (Monoid w, WM.Writer w :> localEs)
61+ => RunIn es (Eff localEs)
62+ -> Writer w (Eff es) a
63+ -> Eff localEs a
64+writerMVar run = \case
65+ Writer aw -> WM.writer aw
66+ Tell w -> WM.tell w
67+ Listen m -> WM.listen (run m)
68+
69+----------------------------------------
70+-- Operations
71+
72+writer :: (Writer w :> es, Monoid w) => (a, w) -> Eff es a
73+writer = send . Writer
74+
75+tell :: (Writer w :> es, Monoid w) => w -> Eff es ()
76+tell = send . Tell
77+
78+listen :: (Writer w :> es, Monoid w) => Eff es a -> Eff es (a, w)
79+listen = send . Listen
80+
81+listens
82+ :: (Writer w :> es, Monoid w)
83+ => (w -> b)
84+ -> Eff es a
85+ -> Eff es (a, b)
86+listens f m = do
87+ (a, w) <- listen m
88+ pure (a, f w)