section ‹ Writer monad›
theory Writer_Monad
imports Monad
begin
subsection ‹ Monoid class›
class monoid = "domain" +
fixes mempty :: "'a"
fixes mappend :: "'a → 'a → 'a"
assumes mempty_left: "∧ ys. mappend⋅ mempty⋅ ys = ys"
assumes mempty_right: "∧ xs. mappend⋅ xs⋅ mempty = xs"
assumes mappend_assoc:
"∧ xs ys zs. mappend⋅ (mappend⋅ xs⋅ ys)⋅ zs = mappend⋅ xs⋅ (mappend⋅ ys⋅ zs)"
subsection ‹ Writer monad type›
text ‹ Below is the standard Haskell definition of a writer monad
; it is an isomorphic copy of the lazy pair type \texttt {(a, w)}.
›
text_raw ‹
begin{verbatim}
Writer w a = Writer { runWriter :: (a, w) }
end{verbatim}
›
text ‹ Since HOLCF does not have a pre-defined lazy pair type, we
base this formalization on an equivalent, more direct definition:
›
text_raw ‹
begin{verbatim}
Writer w a = Writer w a
end{verbatim}
›
text ‹ We can directly translate the above Haskell type definition
‹ tycondef› . \medskip ›
tycondef 'a⋅ 'w writer = Writer (lazy "'w" ) (lazy "'a" )
lemma coerce_writer_abs [simp]: "coerce⋅ (writer_abs⋅ x) = writer_abs⋅ (coerce⋅ x)"
apply (simp add: writer_abs_def coerce_def)
apply (simp add: emb_prj_emb prj_emb_prj DEFL_eq_writer)
done
lemma coerce_Writer [simp]:
"coerce⋅ (Writer⋅ w⋅ x) = Writer⋅ (coerce⋅ w)⋅ (coerce⋅ x)"
unfolding Writer_def by simp
lemma fmapU_writer_simps [simp]:
"fmapU⋅ f⋅ (⊥ ::udom⋅ 'w writer) = ⊥ "
"fmapU⋅ f⋅ (Writer⋅ w⋅ x) = Writer⋅ w⋅ (f⋅ x)"
unfolding fmapU_writer_def writer_map_def fix_const
apply simp
apply (simp add: Writer_def)
done
subsection ‹ Class instance proofs›
instance writer :: ("domain" ) "functor"
proof
fix f g :: "udom → udom" and xs :: "udom⋅ 'a writer"
show "fmapU⋅ f⋅ (fmapU⋅ g⋅ xs) = fmapU⋅ (Λ x. f⋅ (g⋅ x))⋅ xs"
by (induct xs rule: writer.induct) simp_all
qed
instantiation writer :: (monoid) monad
begin
fixrec bindU_writer ::
"udom⋅ 'a writer → (udom → udom⋅ 'a writer) → udom⋅ 'a writer"
where "bindU_writer⋅ (Writer⋅ w⋅ x)⋅ f =
(case f⋅ x of Writer⋅ w'⋅ y ==> Writer⋅ (mappend⋅ w⋅ w')⋅ y)"
lemma bindU_writer_strict [simp]: "bindU⋅ ⊥ ⋅ k = (⊥ ::udom⋅ 'a writer)"
by fixrec_simp
definition
"returnU = Writer⋅ mempty"
instance proof
fix f :: "udom → udom" and m :: "udom⋅ 'a writer"
show "fmapU⋅ f⋅ m = bindU⋅ m⋅ (Λ x. returnU⋅ (f⋅ x))"
by (induct m rule: writer.induct)
(simp_all add: returnU_writer_def mempty_right)
next
fix f :: "udom → udom⋅ 'a writer" and x :: "udom"
show "bindU⋅ (returnU⋅ x)⋅ f = f⋅ x"
by (cases "f⋅ x" rule: writer.exhaust)
(simp_all add: returnU_writer_def mempty_left)
next
fix m :: "udom⋅ 'a writer" and f g :: "udom → udom⋅ 'a writer"
show "bindU⋅ (bindU⋅ m⋅ f)⋅ g = bindU⋅ m⋅ (Λ x. bindU⋅ (f⋅ x)⋅ g)"
apply (induct m rule: writer.induct, simp)
apply (case_tac "f⋅ a" rule: writer.exhaust, simp)
apply (case_tac "g⋅ aa" rule: writer.exhaust, simp)
apply (simp add: mappend_assoc)
done
qed
end
subsection ‹ Transfer properties to polymorphic versions›
lemma fmap_writer_simps [simp]:
"fmap⋅ f⋅ (⊥ ::'a⋅ 'w writer) = ⊥ "
"fmap⋅ f⋅ (Writer⋅ w⋅ x :: 'a⋅ 'w writer) = Writer⋅ w⋅ (f⋅ x)"
unfolding fmap_def [where 'f="'w writer" ]
by (simp_all add: coerce_simp)
lemma return_writer_def: "return = Writer⋅ mempty"
unfolding return_def returnU_writer_def
by (simp add: coerce_simp eta_cfun)
lemma bind_writer_simps [simp]:
"bind⋅ (⊥ :: 'a⋅ 'w::monoid writer)⋅ f = ⊥ "
"bind⋅ (Writer⋅ w⋅ x :: 'a⋅ 'w::monoid writer)⋅ k =
(case k⋅ x of Writer⋅ w'⋅ y ==> Writer⋅ (mappend⋅ w⋅ w')⋅ y)"
unfolding bind_def
apply (simp add: coerce_simp)
apply (cases "k⋅ x" rule: writer.exhaust)
apply (simp_all add: coerce_simp)
done
lemma join_writer_simps [simp]:
"join⋅ ⊥ = (⊥ :: 'a⋅ 'w::monoid writer)"
"join⋅ (Writer⋅ w⋅ (Writer⋅ w'⋅ x)) = Writer⋅ (mappend⋅ w⋅ w')⋅ x"
unfolding join_def by simp_all
subsection ‹ Extra operations›
definition tell :: "'w → unit⋅ ('w::monoid writer)"
where "tell = (Λ w. Writer⋅ w⋅ ())"
end
Messung V0.5 in Prozent C=68 H=90 G=79
¤ Dauer der Verarbeitung: 0.8 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland