Saturday, October 1, 2011

HaTeX 3 - Two styles

Since the last post about this topic (previous notes), I worked on HaTeX 3 and it is almost ended. This post will response a question about the "Applicative vs Monadic" section of the last post.

Example over HaTeX 2

Let be the next simple example (it works with HaTeX 2):

{-# LANGUAGE OverloadedStrings #-}

example :: Monad m => LaTeX m
example = do
  documentclass [] article
  author "Daniel Díaz"
  title "Example"
  document $ do maketitle
                "Hello, world!"

Here, expressions like documentclass [] article and title "Example" have type Monad m => LaTeX m, where LaTeX is a monad transformer. Thus, they are actions over a monad and we can put all of them in a do sequence. Each action, appends in the state of the LaTeX monad a piece of LaTeX code. For instance, for title "Example" it appends the code \title{Example}.

Working with HaTeX 3: First style

As I mentioned in the last post, there is a new datatype LaTeX describing the LaTeX syntax. LaTeX combinators (like author an title) still exist, but now you can use them in two different ways. What I meant with applicative style is to use these combinators without the presence of any monad. You create an expression of type LaTeX, and you combine them with the monoid operator (<>), alias of the mappend method (See the Data.Monoid module).

Let's write the example this way:

{-# LANGUAGE OverloadedStrings #-}

example :: LaTeX
example =
    documentclass [] article
 <> author "Daniel Díaz"
 <> title "Example"
 <> document (maketitle
           <> "Hello, world!")

Yes, all these operators seem ugly. Even I was forced to write an extra parentheses. But I like you can do all the work without monads.

Working with HaTeX 3: Second style

Now, we are interested in take back the do notation. But we don't want to do every work twice. Indeed, if we did this work manually, we would have to define all entities (including commenting, type signature and exposing in the export list) twice! That's really bad!

The solution was HaTeX-meta. HaTeX-meta is a program that reads a subset of the HaTeX modules (those that define LaTeX combinators) and generates automatically an analogous module that export the combinators with monadic types. And preserving their documentation! These modules have the same module name, but followed by .Monad, and import their originals no-monadic functions to build the new monadic ones.

So, now you can write LaTeX code with HaTeX using do notation with the new type-system. The example above stay almost equal if you import the monadic modules of HaTeX 3:

{-# LANGUAGE OverloadedStrings #-}

example :: Monad m => LaTeXT_ m
example = do
  documentclass [] article
  author "Daniel Díaz"
  title "Example"
  document $ do maketitle
                "Hello, world!"



Closure

I hope this was understandable enough. For now, this is all about HaTeX 3. Next posts will be about HaTeX-meta and HaTeX 3 release notes. The official release will be soon, but the code will be available before.

Thanks for read,
Daniel Díaz.

3 comments:

Antoine said...

You could also do what the authors of blaze-html have done - they have a core HTML type which supports both Monoid and Monad operations:

type Html = HtmlM ()

The type HtmlM a is then both a monad and a monoid.

Link

Daniel Díaz said...

@Antoine

Correct. But HtmlM is not really a monad. If you take a look to the bind implementation:

h1 >>= f = h1 >> f (error "...")

You can't actually use it like a monad. It seems the Monad instance for HtmlM is done only for the do notation.

However, LaTeXT is a real monad. Well, more accurately, is a monad transformer.

I use blaze-html steadily, and I like it, but I'd like to intercalate computations. For instance, to read a file which content I want to include in my HTML code, without the need of do all monad stuff (like IO) before start to calling the Html functions.

Thus, with HaTeX, you can do something like:

ex = do
   "File content:"
   t <- lift $ readFile "foo"
   verbatim $ fromString t

I find this useful.

Antoine said...

Your example is using monadic syntax (like blaze), but it isn't monadic in nature - you're not using the output of "verbatim" to determine which file to read.

Either you can pass in the contents of the file or can you pass in the file-name and read it in place - either way, the fundamentals of the program isn't changing, so I guess I don't see the value of doing it the second way.

So even if some application needing the lifting of side-effects, you would still only ever need an Applicative transformer, I think! But maybe I'm thinking about it the wrong way.

That isn't to say you don't have a cool library - I'm a fan of both Haskell and LaTeX, so it is nice to see them together!