packages feed

hatex-guide-1.2.0.0: src/monad.htxg

#LaTeX blocks and the Writer monad#

##The Writer Monad##
Fixed a monoid \{M\}, the \{M\}-writer monad is just all possible pairs of elements from \{M\}
and elements from other types. Thus, the Haskell declaration is as follows\f
Some authors write it using tuples, like this: \{data W m a = W (a,m)\}.\f:

\[
data W m a = W m a
\]

Note that to get the monad we need to fix the type \{m\} (kind of monads is \{* -> *\}). To inject
an arbitrary value into the monad (the Haskell \{return\} function) we use the neutral element (\{mempty\})
of the monoid.

\[
inject :: Monoid m => a -> W m a
inject a = W mempty a
\]

Think that no other element of \{m\} is possible to think: it is the only element we know of it!
Like any other monad, \{W m\} is also a \{Functor\}. We just apply the function to the value.

\[
instance Functor (W m) where
 fmap f (W m a) = W m (f a)
\]

Every \{Monad\} instance can be given by the two monad operations \{inject\} and \{join\}. We already
defined the \{inject\} function. The other one deletes one monad type constructor.

\[
join :: Monoid m => W m (W m a) -> W m a
join (W m (W m' a)) = W (mappend m m') a
\]

In this function we use the other \{Monoid\} method to combine both values. It is important to
note that in both monad operations \{inject\} and \{join\} we used \{mempty\} and \{mappend\}
respectively. In practice, this is because they act equal. Indeed, they are equal if we forget the
\{a\} value. Now, we are ready to define the \{Monad\} instance:

\[
instance Monoid m => Monad (W m) where
 return  = inject
 w >>= f = join (fmap f w)
\]

There is nothing to say about this instance. It is and standard definition valid to any monad.

What we have done here is to hide in a monad a monoid with all its operations. We have created a
machine that operates monoid values. To insert a value into the machine we need the \{tell\}
function:

\[
tell :: m -> W m ()
tell m = W m ()
\]

When we execute the machine, it returns to us the result of operate all the values we have put on it.

\[
execute :: W m a -> m
execute (W m a) = m
\]

Let's see the machine working. For example, the \{Int\} type with addition forms a \{Monoid\}.

\[
instance Monoid Int where
 mempty = 0
 mappend = (+)

example :: Int
example = execute $ do
  tell 1
  tell 2
  tell 3
  tell 4
\]

When we evaluate \{example\} we get \{10\}, as expected. Using \{mapM_\} we can rewrite \{example\}.

\[
example :: Int
example = execute $ mapM_ tell [ 1 .. 4 ]
\]

|machine.png|

##The LaTeX Monad##

Let's go back to the \{LaTeX\} type. Since \{LaTeX\} is an instance of \{Monoid\} we can construct
its correspondent \{Writer\} monad.

\[
type LaTeXW = W LaTeX
\]

The \{W\} machine is waiting now for \{LaTeX\} values.

\[
example :: LaTeX
example = execute $ do
  tell $ documentclass [] article
  tell $ author "Monads lover"
  tell $ title "LaTeX and the Writer Monad"
\]

We put all that blocks in the machine, and it returns the concatenated block. We saved a lot of
\{mappend\}'s, but we now have a lot of \{tell\}'s. No problem. Just redefine each function of
blocks with \{tell\} and \{execute\}.

\[
author' :: LaTeXW a -> LaTeXW ()
author' = tell . author . execute
\]

If it is done in a similar way with \{documentclass\} and \{title\}, every \{tell\} in \{example\}
disappears.

\[
example :: LaTeX
example = execute $ do
  documentclass' [] article
  author' "Monads lover"
  title' "LaTeX and the Writer Monad"
\]

And we can now use the \{LaTeX\} machine more comfortably. However, we have all functions duplicated.
This is why the \{LaTeXC\} class exists. We are going to talk about it later.

##Composing monads##

To add flexibility to \hatex, the writer monad explained above is defined as a monad transformer,
named \{LaTeXT\}. The way to use it is the same, there are just a few changes.

The first change is in type signatures. We need to carry an inner monad in every type.

\[
foo :: Monad m => LaTeXT m a
\]

However, in practice, we can avoid it. Say we going to use an specific monad \{M\}.

\[
type LaTeXW = LaTeXT M

foo :: LaTeXW a
\]

Now, type signatures remain unchanged.

The other change is a new feature: the \{lift\} function. With it we can do any computation
of our inner monad at any time. For example, suppose we want to output some code we have in
the file /foo.hs/. Instead of copy all its content, or read and carry it as an argument along the code,
you can simply read that file using \{lift\} wherever you want.

\[
type LaTeXIO = LaTeXT IO

readCode :: FilePath -> LaTeXIO ()
readCode fp = lift (readFileTex fp) >>= verbatim . raw

example :: LaTeXIO ()
example = do
  "This is the code I wrote this morning:"
  readCode "foo.hs"
  "It was a funny exercise."
\]

Different monads will give different features. In the case we are not interested in any of
these features, it is enough to use the Identity monad.

\[
type LaTeXW = LaTeXT Identity
\]