Built with Alectryon, running Coq+SerAPI v8.16.0+0.16.3. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use instead of Ctrl.
From Tealeaves Require Export
  Classes.Monoid
  Functors.Early.Reader.

From Tealeaves Require Import
  Classes.Kleisli.Monad
  Classes.Kleisli.Comonad
  Classes.Categorical.Monad
  Classes.Categorical.Comonad
  Classes.Categorical.Bimonad.

Import Product.Notations.
Import Functor.Notations.
Import Monoid.Notations.
Import Categorical.Monad.Notations.
Import Categorical.Comonad.Notations.
Import Kleisli.Monad.Notations.
Import Kleisli.Comonad.Notations.

#[local] Generalizable Variables W T F A M.

(** * Writer monad *)
(**********************************************************************)

(** ** Categorical instance *)
(** In the even that [A] is a monoid, the product functor forms a
    monad. The return operation maps <<b>> to <<(1, b)>> where <<1>>
    is the monoid unit.  The join operation monoidally combines the
    two monoid values. *)
(**********************************************************************)
Section writer_monad.

  Context
    `{Monoid M}.

  #[export] Instance Join_writer: Join (prod M) :=
    fun (A: Type) (p: M * (M * A)) =>
      map_fst (uncurry (@monoid_op M _)) (α^-1 p).

  #[export] Instance Return_writer: Return (prod M) :=
    fun A (a: A) => (Ƶ, a).

  
M: Type
op: Monoid_op M
unit0: Monoid_unit M
H: Monoid M

Natural (@ret (prod M) Return_writer)
M: Type
op: Monoid_op M
unit0: Monoid_unit M
H: Monoid M

Natural (@ret (prod M) Return_writer)
M: Type
op: Monoid_op M
unit0: Monoid_unit M
H: Monoid M

forall (A B : Type) (f : A -> B), map f ∘ η = η ∘ map f
M: Type
op: Monoid_op M
unit0: Monoid_unit M
H: Monoid M
A, B: Type
f: A -> B

map f ∘ η = η ∘ map f
now ext a. Qed.
M: Type
op: Monoid_op M
unit0: Monoid_unit M
H: Monoid M

Natural (@join (prod M) Join_writer)
M: Type
op: Monoid_op M
unit0: Monoid_unit M
H: Monoid M

Natural (@join (prod M) Join_writer)
M: Type
op: Monoid_op M
unit0: Monoid_unit M
H: Monoid M

forall (A B : Type) (f : A -> B), map f ∘ μ = μ ∘ map f
M: Type
op: Monoid_op M
unit0: Monoid_unit M
H: Monoid M
A, B: Type
f: A -> B

map f ∘ μ = μ ∘ map f
now ext [x [x' a]]. Qed. #[export, program] Instance Monad_Categorical_writer: Monad (prod M). Solve Obligations with (intros; unfold transparent tcs; ext p; unfold compose in *; destruct_all_pairs; cbn; now simpl_monoid). End writer_monad. (** ** Tensor Strength Makes any <<T ∘ (W ×)>> a Monad *) (**********************************************************************) #[export] Instance BeckDistribution_strength (W: Type) (T: Type -> Type) `{Map_T: Map T}: BeckDistribution (W ×) T := (@strength T _ W). Section strength_as_writer_distributive_law. Import Strength.Notations. Context `{Monoid W}.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F

forall A : Type, σ ∘ η = map (η)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F

forall A : Type, σ ∘ η = map (η)
reflexivity. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F

forall A : Type, σ ∘ μ = map (μ) ∘ σ ∘ map (σ)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F

forall A : Type, σ ∘ μ = map (μ) ∘ σ ∘ map (σ)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F
A: Type

σ ∘ μ = map (μ) ∘ σ ∘ map (σ)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F
A: Type
w1, w2: W
t: F A

(σ ∘ μ) (w1, (w2, t)) = (map (μ) ∘ σ ∘ map (σ)) (w1, (w2, t))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F
A: Type
w1, w2: W
t: F A

map (pair (w1 ● w2)) (id t) = map (μ) (map (pair (id w1)) (map (pair w2) t))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F
A: Type
w1, w2: W
t: F A

(map (pair (w1 ● w2)) ∘ id) t = map (μ) ((map (pair (id w1)) ∘ map (pair w2)) t)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F
A: Type
w1, w2: W
t: F A

(map (pair (w1 ● w2)) ∘ id) t = map (μ) (map (pair (id w1) ∘ pair w2) t)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F
A: Type
w1, w2: W
t: F A

(map (pair (w1 ● w2)) ∘ id) t = (map (μ) ∘ map (pair (id w1) ∘ pair w2)) t
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
F: Type -> Type
Map_F: Map F
H0: Functor F
A: Type
w1, w2: W
t: F A

(map (pair (w1 ● w2)) ∘ id) t = map (μ ∘ (pair (id w1) ∘ pair w2)) t
reflexivity. Qed. Context `{Categorical.Monad.Monad T}. #[export, program] Instance BeckDistributiveLaw_strength: BeckDistributiveLaw (W ×) T := {| bdist_join_r := strength_join T W; bdist_unit_r := strength_ret T W; bdist_join_l := strength_join_l; bdist_unit_l := strength_ret_l; |}. #[export] Instance Monad_Compose_Writer: Monad (T ∘ (W ×)) := Monad_Beck. End strength_as_writer_distributive_law. (** ** Writer Bimonad Instances *) (**********************************************************************) Section writer_bimonad_instance. Context `{Monoid W}.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, bdist (prod W) (prod W) ∘ bdist (prod W) (prod W) = id
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, bdist (prod W) (prod W) ∘ bdist (prod W) (prod W) = id
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

bdist (prod W) (prod W) ∘ bdist (prod W) (prod W) = id
now ext [? [? ?]]. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, extract ∘ bdist (prod W) (prod W) = map extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, extract ∘ bdist (prod W) (prod W) = map extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

extract ∘ bdist (prod W) (prod W) = map extract
now ext [w1 [w2 a]]. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, map extract ∘ bdist (prod W) (prod W) = extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, map extract ∘ bdist (prod W) (prod W) = extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

map extract ∘ bdist (prod W) (prod W) = extract
now ext [w1 [w2 a]]. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, extract ∘ η = id
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, extract ∘ η = id
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

extract ∘ η = id
reflexivity. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, coμ ∘ η = η ∘ η
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, coμ ∘ η = η ∘ η
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

coμ ∘ η = η ∘ η
reflexivity. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, extract ∘ μ = extract ∘ extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, extract ∘ μ = extract ∘ extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

extract ∘ μ = extract ∘ extract
now ext [w1 [w2 a]]. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, coμ ∘ μ = map (μ) ∘ μ ∘ map (bdist (prod W) (prod W)) ∘ coμ ∘ map coμ
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, coμ ∘ μ = map (μ) ∘ μ ∘ map (bdist (prod W) (prod W)) ∘ coμ ∘ map coμ
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

coμ ∘ μ = map (μ) ∘ μ ∘ map (bdist (prod W) (prod W)) ∘ coμ ∘ map coμ
now ext [w1 [w2 a]]. Qed. #[export] Instance Bimonad_Writer: Bimonad (W ×) := {| bimonad_monad := Monad_Categorical_writer; bimonad_comonad := Comonad_reader W; Bimonad.bimonad_dist_counit_l := @bimonad_dist_counit_l; Bimonad.bimonad_dist_counit_r := @bimonad_dist_counit_r; Bimonad.bimonad_distributive_law := BeckDistributiveLaw_strength; Bimonad.bimonad_cup := @bimonad_cup; Bimonad.bimonad_cap := @bimonad_cap; Bimonad.bimonad_baton := @bimonad_baton; Bimonad.bimonad_butterfly := @bimonad_butterfly; |}. End writer_bimonad_instance. (** ** Kleisli Monad Instance *) (**********************************************************************) Section writer_monad. Context `{Monoid W}. #[export] Instance Return_Writer: Return (W ×) := fun A (a: A) => (Ƶ, a). #[export] Instance Bind_Writer: Bind (W ×) (W ×) := fun A B (f: A -> W * B) (p: W * A) => map_fst (uncurry (@monoid_op W _)) (α^-1 (map_snd f p)).
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

Natural (@ret (prod W) Return_Writer)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

Natural (@ret (prod W) Return_Writer)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall (A B : Type) (f : A -> B), map f ∘ η = η ∘ map f
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> B

map f ∘ η = η ∘ map f
now ext a. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall (A B : Type) (f : A -> W * B), bind f ∘ η = f
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall (A B : Type) (f : A -> W * B), bind f ∘ η = f
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> W * B

bind f ∘ η = f
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> W * B
a: A

(bind f ∘ η) a = f a
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> W * B
a: A

bind f (η a) = f a
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> W * B
a: A

map_fst (uncurry monoid_op) (α^-1 (map_snd f (Ƶ, a))) = f a
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> W * B
a: A

map_fst (uncurry monoid_op) (let (y, z) := f a in (id Ƶ, y, z)) = f a
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> W * B
a: A
w: W
b: B

map_fst (uncurry monoid_op) (id Ƶ, w, b) = (w, b)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> W * B
a: A
w: W
b: B

(id Ƶ ● w, id b) = (w, b)
now simpl_monoid. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, bind (η) = id
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall A : Type, bind (η) = id
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

bind (η) = id
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
m: W
a: A

bind (η) (m, a) = id (m, a)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
m: W
a: A

map_fst (uncurry monoid_op) (α^-1 (map_snd (fun a : A => (Ƶ, a)) (m, a))) = id (m, a)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
m: W
a: A

(id m ● Ƶ, id a) = id (m, a)
now simpl_monoid. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall (A B C : Type) (g : B -> W * C) (f : A -> W * B), bind g ∘ bind f = bind (g ⋆ f)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W

forall (A B C : Type) (g : B -> W * C) (f : A -> W * B), bind g ∘ bind f = bind (g ⋆ f)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B

bind g ∘ bind f = bind (g ⋆ f)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A

(bind g ∘ bind f) (m, a) = bind (g ⋆ f) (m, a)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A

((fun p : W * B => map_fst (uncurry monoid_op) (α^-1 (map_snd g p))) ∘ (fun p : W * A => map_fst (uncurry monoid_op) (α^-1 (map_snd f p)))) (m, a) = map_fst (uncurry monoid_op) (α^-1 (map_snd (g ⋆ f) (m, a)))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A

map_fst (uncurry monoid_op) (α^-1 (map_snd g (map_fst (uncurry monoid_op) (α^-1 (map_snd f (m, a)))))) = map_fst (uncurry monoid_op) (α^-1 (map_snd (fun a : A => map_fst (uncurry monoid_op) (α^-1 (map_snd g (f a)))) (m, a)))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A

map_fst (uncurry monoid_op) (α^-1 (map_snd g (map_fst (uncurry monoid_op) (let (y, z) := f a in (id m, y, z))))) = map_fst (uncurry monoid_op) (let (y, z) := map_fst (uncurry monoid_op) (α^-1 (map_snd g (f a))) in (id m, y, z))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A

map_fst (uncurry monoid_op) (α^-1 (map_snd g (map_fst (uncurry monoid_op) (let (y, z) := f a in (m, y, z))))) = map_fst (uncurry monoid_op) (let (y, z) := map_fst (uncurry monoid_op) (α^-1 (map_snd g (f a))) in (m, y, z))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A
w: W
b: B

map_fst (uncurry monoid_op) (α^-1 (map_snd g (map_fst (uncurry monoid_op) (m, w, b)))) = map_fst (uncurry monoid_op) (let (y, z) := map_fst (uncurry monoid_op) (α^-1 (map_snd g (w, b))) in (m, y, z))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A
w: W
b: B

map_fst (uncurry monoid_op) (let (y, z) := g (id b) in (m ● w, y, z)) = map_fst (uncurry monoid_op) (let (y, z) := map_fst (uncurry monoid_op) (let (y, z) := g b in (id w, y, z)) in (m, y, z))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A
w: W
b: B

map_fst (uncurry monoid_op) (let (y, z) := g b in (m ● w, y, z)) = map_fst (uncurry monoid_op) (let (y, z) := map_fst (uncurry monoid_op) (let (y, z) := g b in (w, y, z)) in (m, y, z))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A
w: W
b: B
w0: W
c: C

map_fst (uncurry monoid_op) (m ● w, w0, c) = map_fst (uncurry monoid_op) (let (y, z) := map_fst (uncurry monoid_op) (w, w0, c) in (m, y, z))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A
w: W
b: B
w0: W
c: C

((m ● w) ● w0, id c) = (m ● (w ● w0), id (id c))
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> W * C
f: A -> W * B
m: W
a: A
w: W
b: B
w0: W
c: C

((m ● w) ● w0, c) = (m ● (w ● w0), c)
now simpl_monoid. Qed. #[export] Instance RightPreModule_writer: Kleisli.Monad.RightPreModule (W ×) (W ×) := {| kmod_bind1 := Writer_kmon_bind1; kmod_bind2 := Writer_kmon_bind2; |}. #[export] Instance Monad_writer: Kleisli.Monad.Monad (W ×) := {| kmon_bind0 := Writer_kmon_bind0; |}. (** ** Miscellaneous Properties *) (********************************************************************)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

forall w : W, extract ∘ pair w = id
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

forall w : W, extract ∘ pair w = id
reflexivity. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

forall w : W, extract ∘ incr w = extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

forall w : W, extract ∘ incr w = extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
w: W

extract ∘ incr w = extract
now ext [w' a]. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

forall w : W, extract ⦿ w = extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type

forall w : W, extract ⦿ w = extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
w: W

extract ⦿ w = extract
now ext [w' a]. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> B

forall w : W, (f ∘ extract) ⦿ w = f ∘ extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> B

forall w : W, (f ∘ extract) ⦿ w = f ∘ extract
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: A -> B
w: W

(f ∘ extract) ⦿ w = f ∘ extract
now ext [w' a]. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type

forall (f : W * A -> B) (w : W), f ⦿ w ∘ η = f ∘ pair w
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type

forall (f : W * A -> B) (w : W), f ⦿ w ∘ η = f ∘ pair w
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> B
w: W

f ⦿ w ∘ η = f ∘ pair w
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> B
w: W
a: A

(f ⦿ w ∘ η) a = (f ∘ pair w) a
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> B
w: W
a: A

f (op w unit0, a) = f (w, a)
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> B
w: W
a: A

f (w ● Ƶ, a) = f (w, a)
now simpl_monoid. Qed.
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
op0: Monoid_op W
unit1: Monoid_unit W
H0: Monoid W

forall A : Type, uncurry incr = μ
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
op0: Monoid_op W
unit1: Monoid_unit W
H0: Monoid W

forall A : Type, uncurry incr = μ
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
op0: Monoid_op W
unit1: Monoid_unit W
H0: Monoid W
A: Type

uncurry incr = μ
W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
op0: Monoid_op W
unit1: Monoid_unit W
H0: Monoid W
A: Type
w1, w2: W
a: A

uncurry incr (w1, (w2, a)) = μ (w1, (w2, a))
reflexivity. Qed. End writer_monad.