/
Writer.purs
118 lines (102 loc) · 2.46 KB
/
Writer.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
module Run.Writer
( Writer(..)
, WRITER
, _writer
, liftWriter
, liftWriterAt
, tell
, tellAt
, censor
, censorAt
, foldWriter
, foldWriterAt
, runWriter
, runWriterAt
) where
import Prelude
import Data.Either (Either(..))
import Data.Symbol (class IsSymbol)
import Data.Tuple (Tuple(..))
import Prim.Row as Row
import Run (Run, SProxy(..), FProxy)
import Run as Run
data Writer w a = Writer w a
derive instance functorWriter ∷ Functor (Writer w)
type WRITER w = FProxy (Writer w)
_writer ∷ SProxy "writer"
_writer = SProxy
liftWriter ∷ ∀ w a r. Writer w a → Run (writer ∷ WRITER w | r) a
liftWriter = liftWriterAt _writer
liftWriterAt ∷
∀ w a r t s
. IsSymbol s
⇒ Row.Cons s (WRITER w) t r
⇒ SProxy s
→ Writer w a
→ Run r a
liftWriterAt = Run.lift
tell ∷ ∀ w r. w → Run (writer ∷ WRITER w | r) Unit
tell = tellAt _writer
tellAt ∷
∀ w r t s
. IsSymbol s
⇒ Row.Cons s (WRITER w) t r
⇒ SProxy s
→ w
→ Run r Unit
tellAt sym w = liftWriterAt sym (Writer w unit)
censor ∷ ∀ w a r. (w → w) → Run (writer ∷ WRITER w | r) a → Run (writer ∷ WRITER w | r) a
censor = censorAt _writer
censorAt ∷
∀ w a r t s
. IsSymbol s
⇒ Row.Cons s (WRITER w) t r
⇒ SProxy s
→ (w → w)
→ Run r a
→ Run r a
censorAt sym = loop
where
handle = Run.on sym Left Right
loop f r = case Run.peel r of
Left a → case handle a of
Left (Writer w n) → do
tellAt sym (f w)
loop f n
Right _ →
Run.send a >>= loop f
Right a →
pure a
foldWriter ∷ ∀ w b a r. (b → w → b) → b → Run (writer ∷ WRITER w | r) a → Run r (Tuple b a)
foldWriter = foldWriterAt _writer
foldWriterAt ∷
∀ w b a r t s
. IsSymbol s
⇒ Row.Cons s (WRITER w) t r
⇒ SProxy s
→ (b → w → b)
→ b
→ Run r a
→ Run t (Tuple b a)
foldWriterAt sym = loop
where
handle = Run.on sym Left Right
loop k w r = case Run.peel r of
Left a → case handle a of
Left (Writer w' n) →
loop k (k w w') n
Right a' →
Run.send a' >>= foldWriterAt sym k w
Right a →
pure (Tuple w a)
runWriter ∷ ∀ w a r. Monoid w ⇒ Run (writer ∷ WRITER w | r) a → Run r (Tuple w a)
runWriter = runWriterAt _writer
runWriterAt ∷
∀ w a r t s
. IsSymbol s
⇒ Monoid w
⇒ Row.Cons s (WRITER w) t r
⇒ SProxy s
→ Run r a
→ Run t (Tuple w a)
runWriterAt sym = foldWriterAt sym (<>) mempty