example definition program theorem

The writer monad encodes logging: newtype Writer w a = Writer (a, w) where the log type w is a Monoid — needed to append logs and to provide the trivial empty log.

instance Monoid w => Monad (Writer w) where
  (Writer (a, w)) >>= k = let Writer (b, w') = k a in Writer (b, mappend w w')
  return a = Writer (a, mempty)

Sources: DaoFP §14.1, §14.4 (“Logging”), §15.3 (“M-sets and the writer monad”); §16 (the dual costate/Comonad); CTfS §3.1.2 (monoid actions), Slogan 4.2.1.2

-sets are CTfS’s monoid actions — e.g. a Finite State Machine is a -set.

From an adjunction (Monads from Adjunctions). An -set is a set with a left action of a monoid , , ; -sets and equivariant maps () form . The forgetful has left adjoint with free action : an equivariant is determined by its values on , namely , giving . Unit is return; counit ; and is — join (Writer (Writer (x, m), n)) = Writer (x, mappend n m).

Docs: plain Julia — Catlab has no dedicated API for this; related: Catlab v0.16 docs · GATlab standard library

# Writer over the String monoid: values paired with logs
ret(a) = (a, "")
bind((a, w), k) = ((b, w′) = k(a); (b, w * w′))
step1(x) = (x + 1, "inc; ")
step2(x) = (2x, "double; ")
bind(bind(ret(3), step1), step2)      # (8, "inc; double; ")
import Mathlib
-- an M-set is a MulAction; the free M-set on S is S × M with the free (right-regular) action
#check @MulAction
#check @MulAction.toFun
-- Writer as a state-free logging monad:
def Writer (w α : Type) := α × w
def Writer.bind [Monoid w] (m : Writer w α) (k : α → Writer w β) : Writer w β :=
  let (b, w') := k m.1; (b, m.2 * w')
newtype Writer w a = Writer (a, w)
runWriter :: Writer w a -> (a, w)
runWriter (Writer p) = p
instance Functor (Writer w) where fmap f (Writer (a, w)) = Writer (f a, w)
instance Monoid w => Applicative (Writer w) where
  pure a = Writer (a, mempty)
  Writer (f, w) <*> Writer (a, w') = Writer (f a, w <> w')
instance Monoid w => Monad (Writer w) where
  Writer (a, w) >>= k = let Writer (b, w') = k a in Writer (b, w <> w')
tell :: w -> Writer w ()
tell w = Writer ((), w)