Skip to content

Commit f7bfeba

Browse files
cmcmA20gallais
andauthored
[resolves agda#1333] writer transformer (agda#1850)
* Writer monad (CPS encoded) add more instances for writer, change output level in RawMonadError Co-authored-by: Guillaume Allais <[email protected]>
1 parent eda81db commit f7bfeba

File tree

13 files changed

+502
-8
lines changed

13 files changed

+502
-8
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,15 @@ Non-backwards compatible changes
591591
This is needed because `MonadState S M` does not pack a `Monad M` instance anymore
592592
and so we cannot define `modify f` as `get >>= λ s → put (f s)`.
593593

594+
* `MonadWriter 𝕎 M` is defined similarly:
595+
```agda
596+
writer : W × A → M A
597+
listen : M A → M (W × A)
598+
pass : M ((W → W) × A) → M A
599+
```
600+
with `tell` defined as a derived notion.
601+
Note that `𝕎` is a `RawMonoid`, not a `Set` and `W` is the carrier of the monoid.
602+
594603
* New modules:
595604
```
596605
Data.List.Effectful.Transformer
@@ -613,6 +622,11 @@ Non-backwards compatible changes
613622
Effect.Monad.State.Instances
614623
Effect.Monad.State.Transformer
615624
Effect.Monad.State.Transformer.Base
625+
Effect.Monad.Writer
626+
Effect.Monad.Writer.Indexed
627+
Effect.Monad.Writer.Instances
628+
Effect.Monad.Writer.Transformer
629+
Effect.Monad.Writer.Transformer.Base
616630
IO.Effectful
617631
IO.Instances
618632
```

src/Effect/Monad/Error/Transformer.agda

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ private
2121
variable
2222
f ℓ : Level
2323
A B : Set
24-
M : Set f Set f
24+
M : Set f Set
2525

2626
------------------------------------------------------------------------
2727
-- Error monad operations
2828

2929
record RawMonadError
30-
(M : Set (e ⊔ a) Set (e ⊔ a))
31-
: Set (suc (e ⊔ a)) where
30+
(M : Set (e ⊔ a) Set )
31+
: Set (suc (e ⊔ a) ⊔ ℓ) where
3232
field
3333
throw : E M A
3434
catch : M A (E M A) M A

src/Effect/Monad/IO.agda

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ record RawMonadIO
3232
liftIO : IO A M A
3333

3434
------------------------------------------------------------------------
35-
-- Reader monad specifics
35+
-- IO monad specifics
3636

3737
monadIO : RawMonadIO {f} IO
3838
monadIO = record { liftIO = id }
@@ -50,3 +50,10 @@ liftReaderT : ∀ {R} → RawMonadIO M → RawMonadIO (ReaderT R M)
5050
liftReaderT MIO = record
5151
{ liftIO = λ io mkReaderT (λ r liftIO io)
5252
} where open RawMonadIO MIO
53+
54+
open import Effect.Monad.Writer.Transformer.Base using (WriterT; mkWriterT)
55+
56+
liftWriterT : {f 𝕎} RawFunctor M RawMonadIO M RawMonadIO (WriterT {f = f} 𝕎 M)
57+
liftWriterT M MIO = record
58+
{ liftIO = λ io mkWriterT (λ w (w ,_) <$> liftIO io)
59+
} where open RawFunctor M; open RawMonadIO MIO

src/Effect/Monad/IO/Instances.agda

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ instance
1414
ioMonadIO = monadIO
1515
stateTMonadIO = λ {s} {S} {M} {{m}} {{mio}} liftStateT {s} {S} {M} m mio
1616
readerTMonadIO = λ {r} {R} {M} {{mio}} liftReaderT {r} {R} {M} mio
17+
writerTMonadIO = λ {f} {w} {W} {M} {{m}} {{mio}} liftWriterT {f} {w} {W} {M} m mio

src/Effect/Monad/Reader/Instances.agda

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ instance
2222
readerTMonadPlus = λ {s} {S} {f} {M} {{mpl}} monadPlus {s} {S} {f} {M} mpl
2323
readerTMonadT = λ {s} {S} {f} {M} {{mon}} monadT {s} {S} {f} {M} mon
2424
readerTMonadReader = λ {s} {S} {f} {M} {{mon}} monadReader {s} {S} {f} {M} mon
25-
readerTLiftStateT = λ {s} {S₁} {S₂} {f} {M} {{mon}} {{ms}} liftStateT {s} {S₁} {S₂} {f} {M} mon ms
25+
readerTLiftWriterT = λ {s} {S₁} {S₂} {f} {M} {{mo}} {{fun}} {{mr}} liftWriterT {s} {S₁} {S₂} {f} {M} mo fun mr
26+
readerTLiftStateT = λ {s} {S₁} {S₂} {f} {M} {{fun}} {{mr}} liftStateT {s} {S₁} {S₂} {f} {M} fun mr
2627
-- the following instance conflicts with readerTMonadReader so we don't include it
2728
-- readerTLiftReaderT = λ {R} {s} {S} {f} {M} {{ms}} → liftReaderT {R} {s} {S} {f} {M} ms

src/Effect/Monad/Reader/Transformer.agda

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
module Effect.Monad.Reader.Transformer where
1111

12+
open import Algebra using (RawMonoid)
1213
open import Effect.Choice
1314
open import Effect.Empty
1415
open import Effect.Functor
@@ -115,7 +116,19 @@ liftReaderT MRead = record
115116
; local = λ f mx mkReaderT (λ r₂ local f (runReaderT mx r₂))
116117
} where open RawMonadReader MRead
117118

118-
open import Data.Product using (_,_)
119+
open import Data.Product using (_×_; _,_)
120+
open import Effect.Monad.Writer.Transformer.Base
121+
122+
liftWriterT : (MR : RawMonoid r g)
123+
RawFunctor M
124+
RawMonadReader R M
125+
RawMonadReader R (WriterT MR M)
126+
liftWriterT MR M MRead = record
127+
{ reader = λ k mkWriterT λ w ((w ,_) <$> reader k)
128+
; local = λ f mx mkWriterT λ w (local f (runWriterT mx w))
129+
} where open RawMonadReader MRead
130+
open RawFunctor M
131+
119132
open import Effect.Monad.State.Transformer.Base
120133

121134
liftStateT : RawFunctor M

src/Effect/Monad/State/Instances.agda

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ instance
2222
stateTMonadPlus = λ {s} {S} {f} {M} {{mpl}} monadPlus {s} {S} {f} {M} mpl
2323
stateTMonadT = λ {s} {S} {f} {M} {{mon}} monadT {s} {S} {f} {M} mon
2424
stateTMonadState = λ {s} {S} {f} {M} {{mon}} monadState {s} {S} {f} {M} mon
25-
-- the following instance conflicts with stateTMonadState so we don't include it
26-
-- stateTLiftStateT = λ {s} {S₁} {S₂} {f} {M} {{mon}} {{ms}} → liftStateT {s} {S₁} {S₂} {f} {M} mon ms
2725
stateTLiftReaderT = λ {R} {s} {S} {f} {M} {{ms}} liftReaderT {R} {s} {S} {f} {M} ms
26+
stateTLiftWriterT = λ {R} {s} {S} {f} {M} {{fun}} {{mo}} {{ms}} liftWriterT {R} {s} {S} {f} {M} mo fun ms
27+
-- the following instances conflicts with stateTMonadState so we don't include it
28+
-- stateTLiftStateT = λ {s} {S₁} {S₂} {f} {M} {{mon}} {{ms}} → liftStateT {s} {S₁} {S₂} {f} {M} mon ms

src/Effect/Monad/State/Transformer.agda

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ open import Level using (Level; suc; _⊔_)
1010

1111
module Effect.Monad.State.Transformer where
1212

13+
open import Algebra using (RawMonoid)
1314
open import Data.Product using (_×_; _,_; map₂; proj₁; proj₂)
1415
open import Data.Unit.Polymorphic.Base
1516
open import Effect.Choice
@@ -136,3 +137,15 @@ liftReaderT Mon = record
136137
{ gets = λ f mkReaderT (const (gets f))
137138
; modify = λ f mkReaderT (const (modify f))
138139
} where open RawMonadState Mon
140+
141+
open import Effect.Monad.Writer.Transformer.Base
142+
143+
liftWriterT : (MS : RawMonoid s f)
144+
RawFunctor M
145+
RawMonadState S M
146+
RawMonadState S (WriterT MS M)
147+
liftWriterT MS M Mon = record
148+
{ gets = λ f mkWriterT λ w (gets ((w ,_) ∘′ f))
149+
; modify = λ f mkWriterT λ w (const (w , tt) <$> modify f)
150+
} where open RawMonadState Mon
151+
open RawFunctor M

src/Effect/Monad/Writer.agda

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- The writer monad
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --without-K --safe #-}
8+
9+
module Effect.Monad.Writer where
10+
11+
open import Algebra using (RawMonoid)
12+
open import Data.Product using (_×_)
13+
open import Effect.Applicative
14+
open import Effect.Choice
15+
open import Effect.Empty
16+
open import Effect.Functor
17+
open import Effect.Monad
18+
open import Effect.Monad.Identity as Id using (Identity; runIdentity)
19+
open import Function.Base using (_∘′_)
20+
open import Level using (Level)
21+
22+
import Effect.Monad.Writer.Transformer as Trans
23+
24+
private
25+
variable
26+
w ℓ : Level
27+
A : Set w
28+
𝕎 : RawMonoid w ℓ
29+
30+
------------------------------------------------------------------------
31+
-- Re-export the monad writer operations
32+
33+
open Trans public
34+
using (RawMonadWriter)
35+
36+
------------------------------------------------------------------------
37+
-- Writer monad
38+
39+
Writer : (𝕎 : RawMonoid w ℓ) (A : Set w) Set w
40+
Writer 𝕎 = Trans.WriterT 𝕎 Identity
41+
42+
functor : RawFunctor (Writer 𝕎)
43+
functor = Trans.functor Id.functor
44+
45+
module _ {𝕎 : RawMonoid w ℓ} where
46+
47+
open RawMonoid 𝕎 renaming (Carrier to W)
48+
49+
runWriter : Writer 𝕎 A W × A
50+
runWriter ma = runIdentity (Trans.runWriterT ma ε)
51+
52+
applicative : RawApplicative (Writer 𝕎)
53+
applicative = Trans.applicative Id.applicative
54+
55+
monad : RawMonad (Writer 𝕎)
56+
monad = Trans.monad Id.monad
57+
58+
----------------------------------------------------------------------
59+
-- Writer monad specifics
60+
61+
monadWriter : RawMonadWriter 𝕎 (Writer 𝕎)
62+
monadWriter = Trans.monadWriter Id.monad
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- The indexed writer monad
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --without-K --safe #-}
8+
9+
open import Level
10+
11+
module Effect.Monad.Writer.Indexed (a : Level) where
12+
13+
open import Algebra using (RawMonoid)
14+
open import Data.Product using (_×_; _,_; map₁)
15+
open import Data.Unit.Polymorphic
16+
open import Effect.Applicative.Indexed
17+
open import Effect.Monad
18+
open import Effect.Monad.Indexed
19+
open import Function
20+
open import Function.Identity.Effectful as Id using (Identity)
21+
22+
private
23+
variable
24+
w ℓ : Level
25+
A B I : Set
26+
27+
------------------------------------------------------------------------
28+
-- Indexed writer
29+
30+
IWriterT : (𝕎 : RawMonoid w ℓ) IFun I (w ⊔ a) IFun I (w ⊔ a)
31+
IWriterT 𝕎 M i j A = M i j (RawMonoid.Carrier 𝕎 × A)
32+
33+
module _ {M : IFun I (w ⊔ a)} {𝕎 : RawMonoid w ℓ} where
34+
35+
open RawMonoid 𝕎 renaming (Carrier to W)
36+
37+
------------------------------------------------------------------------
38+
-- Indexed writer applicative
39+
40+
WriterTIApplicative : RawIApplicative M RawIApplicative (IWriterT 𝕎 M)
41+
WriterTIApplicative App = record
42+
{ pure = λ x pure (ε , x)
43+
; _⊛_ = λ m n go <$> m ⊛ n
44+
} where
45+
open RawIApplicative App
46+
go : W × (A B) W × A W × B
47+
go (w₁ , f) (w₂ , x) = w₁ ∙ w₂ , f x
48+
49+
WriterTIApplicativeZero : RawIApplicativeZero M
50+
RawIApplicativeZero (IWriterT 𝕎 M)
51+
WriterTIApplicativeZero App = record
52+
{ applicative = WriterTIApplicative applicative
53+
; ∅ =
54+
} where open RawIApplicativeZero App
55+
56+
WriterTIAlternative : RawIAlternative M RawIAlternative (IWriterT 𝕎 M)
57+
WriterTIAlternative Alt = record
58+
{ applicativeZero = WriterTIApplicativeZero applicativeZero
59+
; _∣_ = _∣_
60+
} where open RawIAlternative Alt
61+
62+
------------------------------------------------------------------------
63+
-- Indexed writer monad
64+
65+
WriterTIMonad : RawIMonad M RawIMonad (IWriterT 𝕎 M)
66+
WriterTIMonad Mon = record
67+
{ return = λ x return (ε , x)
68+
; _>>=_ = λ m f do
69+
w₁ , x m
70+
w₂ , fx f x
71+
return (w₁ ∙ w₂ , fx)
72+
} where open RawIMonad Mon
73+
74+
WriterTIMonadZero : RawIMonadZero M RawIMonadZero (IWriterT 𝕎 M)
75+
WriterTIMonadZero Mon = record
76+
{ monad = WriterTIMonad monad
77+
; applicativeZero = WriterTIApplicativeZero applicativeZero
78+
} where open RawIMonadZero Mon
79+
80+
WriterTIMonadPlus : RawIMonadPlus M RawIMonadPlus (IWriterT 𝕎 M)
81+
WriterTIMonadPlus Mon = record
82+
{ monad = WriterTIMonad monad
83+
; alternative = WriterTIAlternative alternative
84+
} where open RawIMonadPlus Mon
85+
86+
------------------------------------------------------------------------
87+
-- Writer monad operations
88+
89+
record RawIMonadWriter {I : Set ℓ} (𝕎 : RawMonoid w ℓ) (M : IFun I (w ⊔ a))
90+
: Set (ℓ ⊔ suc (w ⊔ a)) where
91+
open RawMonoid 𝕎 renaming (Carrier to W)
92+
field
93+
monad : RawIMonad M
94+
writer : {i} (W × A) M i i A
95+
listen : {i j} M i j A M i j (W × A)
96+
pass : {i j} M i j ((W W) × A) M i j A
97+
98+
open RawIMonad monad public
99+
100+
tell : {i} W M i i ⊤
101+
tell = writer ∘′ (_, tt)
102+
103+
listens : {i j} {Z : Set w} (W Z) M i j A M i j (Z × A)
104+
listens f m = listen m >>= return ∘′ map₁ f
105+
106+
censor : {i j} (W W) M i j A M i j A
107+
censor f m = pass (m >>= return ∘′ (f ,_))
108+
109+
110+
WriterTIMonadWriter : {I : Set ℓ} {𝕎 : RawMonoid w ℓ} {M : IFun I (w ⊔ a)}
111+
RawIMonad M RawIMonadWriter 𝕎 (IWriterT 𝕎 M)
112+
WriterTIMonadWriter {𝕎 = 𝕎} Mon = record
113+
{ monad = WriterTIMonad {𝕎 = 𝕎} Mon
114+
; writer = return
115+
; listen = λ m do
116+
w , a m
117+
return (w , w , a)
118+
; pass = λ m do
119+
w , f , a m
120+
return (f w , a)
121+
} where open RawIMonad Mon
122+
open RawMonoid 𝕎 renaming (Carrier to W)

0 commit comments

Comments
 (0)