#LaTeX blocks and the Writer monad# ##The Writer Monad## For any given 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\} (the 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 about the element of \{m\}: there is only one element that it could be! 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 similarly to each other. 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 a standard definition, valid for any monad. What we have done here is to hide a monoid in a monad, with all its operations. We have created a machine that operates on monoidal 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 the result of operating on all the values we have put into 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 corresponding \{Writer\} monad. \[ type LaTeXW = W LaTeX \] The \{W\} machine is now waiting 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 these blocks into the machine, and it returns the concatenated block for us. We just saved a lot of \{mappend\}'s, but we now have a lot of \{tell\}'s instead. No problem, just redefine each function of blocks using \{tell\} and \{execute\}. \[ author' :: LaTeXW a -> LaTeXW () author' = tell . author . execute \] If this is done in a similar way to \{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 duplicated all of our functions. This is why the \{LaTeXC\} class exists. We'll talk about this later. ##Composing monads## To add flexibility to \hatex, the writer monad explained above is defined as a monad transformer, named \{LaTeXT\}. The way we use it is the same, with just a few small changes. The first change is in the type signature. We need to carry an inner monad in every type. \[ foo :: Monad m => LaTeXT m a \] However, in practice, we can avoid this by using type aliases. Say we're going to use a specific monad \{M\}. \[ type LaTeXW = LaTeXT M foo :: LaTeXW a \] Now, the type signatures go back to the way they were. The other change is a new feature: the \{lift\} function. With it we can do any computation on our inner monad at any time. For example, suppose we want to output some code we have in the file /foo.hs/. Instead of copying all of its content, or reading and carrying it as an argument along in 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 each give different features. In the case where we're not interested in any of these features, we can simply use the Identity monad. \[ type LaTeXW = LaTeXT Identity \]