Wednesday, September 14, 2011

HaTeX 3 - Previous notes

As I announced in my provisional webpage (here), I'm preparing a completly new version of HaTeX. It will be the third version. Firstly, I wanted to write some lines about what was, is and will be HaTeX. So here we are.

A bit of history

When I started to write this library, I didn't know too much about LaTeX. I thought: "Well, I want to get LaTeX results, but using Haskell instead of LaTeX". That was my first thinking. But quickly I found other utilities. Mainly, I started to write outputs of my own programs directly in a LaTeX document, or tables contrasting the time employed by different programs solving the same task.

When I did the first upload (it actually was my first upload to Hackage), the way the library worked was storing raw LaTeX code in the state of a writer monad transformer applied to IO. So, when you type author "Daniel Díaz", it appends "\author{Daniel Díaz}" at the end of the state. Thus, HaTeX was really a high-level way to append strings that ought contain LaTeX code. But the library was putting all those backslashes and braces for you!

In the second version, we said goodbye to the IO monad. The monad transformer now becomes free to be composable with the monad of your desire. This was thanks to Alexey Khudyakov, who gave me a very neat feedback and this change as a proposal.

The new datatype

However, I never liked that the LaTeX type was only a type synonym of the Writer monad with a difference string as state. And this is the main point I wanted to change. In HaTeX 3, I defined a datatype representing the LaTeX syntax, so author "Daniel Díaz", now means:

TeXComm "author" [FixArg (TeXRaw "Daniel Díaz")]

Far harder to read! But, if you take a look on it, it is only describing the syntax of that LaTeX expression. You can say that this is the abstract syntax of that expression. And I feel more comfortable working with this datatype. After you have built your LaTeX document, just use the render function to build your final code in the form of a value in the Text type. This also make possible to build a LaTeX parser (I guess I will write one some day).

Following this line, I have also restricted the input of functions to values of a type that make sense with that function. For instance, making a LaTeX tabular, you must to specify how columns are aligned and where to put vertical lines to divide them. Thus, the tabular function have an argument of type [TableSpec], being TableSpec a datatype containing the possible specifications for your table, so you can't put invalid data.

A new module hierarchy

While Text.LaTeX is still the main module, it forks in two submodules: Text.LaTeX.Base and Text.LaTeX.Packages. The former contains all commands and environments that you have without importing others with the usepackage command. The latter have a submodule per LaTeX package. Well, only a few of them are implemented! But you can always request one, or, much better, you can contribute implementing one! The aim of this breakup is to give you the freedom to import only the functions you want without a too big import header. Also, I thought this will help to do code better organized.

Applicative vs Monadic

Maybe, you realized that the author function no longer communicates with any kind of writer monad. In fact, it takes an author's name, and return something of the datatype LaTeX. No monad involved. LaTeX is instance of the Monoid class, so you can append these results with mappend (<>) in order to obtain your final output.

This will involve to repeat many times this operator. We can save this work by the same way we do that the last time: making use of the writer monad. But I have not written, at the moment, any monadic code. My idea is to use some program to, from the source code of a module with these applicative style functions, generate a module with monadic style functions. For instance, if we have:

author :: LaTeX -> LaTeX
author a = TeXComm "author" [FixArg a]

We can write:

author :: Monad m => LaTeX -> LaTeXM m ()
author = tell .

End of this preview

And, for now, this is all I have to say about HaTeX 3. As always, you can do any pre-release suggestion, or discuss about the current course of the library, as it was described here. Finally, I want to apologize for so unstable library. I am only trying to make it better as possible.

Thanks for read,
Daniel Díaz.


laughedelic said...

Great news! Especially about new type-system.
But I don't understand the last section "Applicative vs Monadic". Can you explain these changes more detailed, please?
When will you post the new version? And will you make any tutorial or usage examples for it?

Anonymous said...

How about going the extra mile and doing a tagless DSL? Later on we could provide a Haskell-only LaTeX solution ;-).

Daniel Díaz said...


I hope this could answer your question:

I can't give you a fixed day for the release, but I promise you it will be as soon as posible.

About tutorials or examples, I want to write something. Anyway, the usage of HaTeX 3 is quite similar to HaTeX 2. The main change was in the core of the package and in the module hierarchy. Although there is some additional changes in the API.

Of course, you can contribute with your own examples! I'll be very glad to see how other people use HaTeX.