A program to evaluate Haskell code within LaTeX
Daniel Díaz
The haskintex program is a tool that reads a LaTeX file and evaluates Haskell expressions contained in some specific commands and environments. It allows you to define your own functions, use any GHC Haskell language extension and, in brief, anything you can do within Haskell. You can freely add any Haskell code you need, and make this code appear optionally in the LaTeX output. It is a tiny program, and therefore, easy to understand, use and predict.
To install haskintex from Hackage, use the cabal program:
? cabal update ? cabal install haskintex
This will update your package database and install the latest version of haskintex. Otherwise, you can build the current developing version downloading its code as a zip file.
Note that this page will be updated with every new version released to Hackage, so it reflects the features of the
last released version. If you have a previous version, some of the features explained here may not apply to you.
To check what version you have installed, run haskintex -help.
Consider the following simple example.
\documentclass{article}
\begin{document}
I have \evalhaskell{2+3} fingers in my right hand.
\end{document}
If the above LaTeX code is written in foo.htex, after running haskintex foo.htex
the file foo.tex will be written with:
\documentclass{article}
\begin{document}
I have \verb`5` fingers in my right hand.
\end{document}
The Haskell code 2+3 has been evaluated to 5, and the result has been enclosed
in a verb command. The evaluation is done using
GHC, so it must be installed in order to use haskintex.
The file foo.htex can be processed running hakintex foo as well. When the given
input file does not exist, haskintex adds the .htex extension automatically.
If the file with the added extension does not exist, it throws an error.
Let's go through another example. The factorial function can be implemented recursively in Haskell.
fact :: Int -> Int fact 0 = 1 fact n = n * fact (n-1)
To include this function in the scope of evalhaskell use writehaskell as
shown below.
\documentclass{article}
\begin{document}
\begin{writehaskell}
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n-1)
\end{writehaskell}
While 5 factorial is \evalhaskell{fact 5}, 10 factorial is
\evalhaskell{fact 10}.
\end{document}
Therefore, to add binding definitions use the writehaskell environment,
and to evaluate code use evalhaskell. If the output of an evaluation is
known to be big and it is not desired to be inlined, use evalhaskell as an environment
instead. For example:
\documentclass{article}
\begin{document}
This is the list of numbers from 1 to 1000:
\begin{evalhaskell}
[1..1000]
\end{evalhaskell}
\end{document}
Lines in the output of evalhaskell as environment are bounded to 60
characters. A line break will be introduced if this number is exceeded.
It is possible to use any Haskell type within the evalhaskell command or environment.
Whatever the result is, it will be added to the LaTeX output using the Show instance
given by the type of the input expression. Sometimes, this is good enough, but probably you will
end up wanting a more complex way to display your results. To approach this problem, there is a library
called HaTeX which defines a LaTeX type. Using this library, you can define your
own functions from and to this type. In the other hand, haskintex lets you use the command
hatex. This command receives as input a Haskell expression of type LaTeX
and generates its corresponding LaTeX code as output. It is recommended to take a look at the
HaTeX library to make yourself an idea of the possibilities you have. As an example, this is
how you draw a portion of a logarithmic spiral.
\documentclass{article}
\usepackage{tikz}
\usepackage[utf8]{inputenc}
\author{Daniel Díaz}
\title{Embedding HaTeX in \emph{haskintex}}
\begin{document}
\maketitle
Below is the \emph{Spira Mirabilis} inserted using the HaTeX
package.
\begin{writehaskell}
import Text.LaTeX
import Text.LaTeX.Packages.TikZ.Simple
spiral :: Figure
spiral = LineWidth (Pt 2) $
pathImage 0.01 (0,4) $
\t -> ( a * exp t * cos (b*t)
, a * exp t * sin (b*t)
)
where
a = 0.1 ; b = 4
\end{writehaskell}
\hatex{center $ tikzpicture $ figuretikz spiral}
\end{document}
The output looks like this:
The example above uses functions from the Text.LaTeX.Packages.TikZ.Simple module, which deals
with graphic generation using TikZ scripts. You may take a look to its
API documentation
to fully
understand the given example.
While the hatex command opens tons of possibilities to generate LaTeX code, it suffers from an unfortunate
restriction. Since it only accepts expressions of type LaTeX, it will never accept an expression that
performs IO computations. To solve this, use the iohatex command. It works the same way as the
hatex command does, but it expects an expression of type IO LaTeX instead. Here an example:
\documentclass{article}
\begin{document}
\begin{writehaskell}
import Text.LaTeX
import Data.Time (getCurrentTime)
import Control.Applicative ((<$>))
import Data.String (fromString)
\end{writehaskell}
I am testing the \texttt{iohatex} command when the time is \iohatex{fromString . show <$> getCurrentTime}.
\end{document}
If you include pragmas with the writehaskell environment and run haskintex with the keep
flag, you will notice that the pragma is included below the module ... where clause, and therefore it is not
working. To include pragmas, use the haskellpragmas environment. It would go like this:
\documentclass{article}
\begin{document}
\begin{haskellpragmas}
{-# LANGUAGE OverloadedStrings #-}
\end{haskellpragmas}
\begin{writehaskell}
import Text.LaTeX
overloaded :: LaTeX
overloaded = "This is an Overloaded String."
\end{writehaskell}
\hatex{overloaded}
\end{document}
The place where evalhaskell is called does not really matter.
The function fact can be called before defining it.
\documentclass{article}
\begin{document}
While 5 factorial is \evalhaskell{fact 5}, 10 factorial is
\evalhaskell{fact 10}.
\begin{writehaskell}
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n-1)
\end{writehaskell}
\end{document}
Note that this also applies to pragmas. If you include a pragma at the end (see below), it will still apply to the Haskell code.
\documentclass{article}
\begin{document}
\begin{writehaskell}
import Text.LaTeX
overloaded :: LaTeX
overloaded = "This is an Overloaded String."
\end{writehaskell}
\hatex{overloaded}
\begin{haskellpragmas}
{-# LANGUAGE OverloadedStrings #-}
\end{haskellpragmas}
\end{document}
What haskintex does is to traverse the LaTeX code twice. The first time it creates a Haskell module
with all the code defined with writehaskell and haskellpragmas environments,
placing the pragmas at the beginning of the file. In the second pass, it evaluates
all the evalhaskell calls with the created module imported. Note that this means you have to avoid
duplicated names.
By default, the Haskell code introduced by writehaskell (or haskellpragmas)
will not show up in the processed LaTeX code. To change this, use the visible option.
For example:
\documentclass{article}
\begin{document}
\begin{writehaskell}[visible]
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n-1)
\end{writehaskell}
While 5 factorial is \evalhaskell{fact 5}, 10 factorial is
\evalhaskell{fact 10}.
\end{document}
A verbatim environment will contain the code. To change the default
behavior and make Haskell code visible by default, pass the -visible flag when
invoking haskintex. Use then the hidden option to hide specific
calls to writehaskell (or haskellpragmas).
\documentclass{article}
\begin{document}
\begin{writehaskell}[hidden]
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n-1)
\end{writehaskell}
While 5 factorial is \evalhaskell{fact 5}, 10 factorial is
\evalhaskell{fact 10}.
\end{document}
You can still use the visible option but it will be pretty much useless. However,
it may be useful if you are switching the -visible flag on and off frequently.
haskintex to remember the value of an expression to avoid compute
it twice. This, however, has a drawback: the expression won't be evaluated again, even if
its actual value changes. These are the tools you can use to control this feature:
hatex, iohatex,
and evalhaskell commands and environments. When the enclosed expression is
evaluated, its result will be stored in the memo tree (the structure haskintex uses
internally to store pairs of unevaluated code and its result). The next time the same
expression is found, if it is marked with memo as well, it won't be evaluated again:
the stored result will be used instead.
memo.
It will force a given Haskell expression to be evaluated every time, not using the memo tree.
memo option everywhere it can be applied,
except for those places where the notmemo option has been specified.
To sum up: place the memo option to those expressions whose value don't change
over time and you don't want to compute twice. And let haskintex do the rest.
Alternatively, use the memo flag and apply the notmemo option
to those expressions whose value may change over time.
If haskintex is running inside a cabal sandbox environment, it will use the sandbox
package db when evaluating Haskell code. If you don't want this to happen, use the
-nosandbox flag and the sandbox package db will be ignored.
Below a list of the flags accepted by the program. Any argument starting with -
will be recognized as a flag, even if it is not defined (in which case, it will have no effect).
Anything else will be considered an input file. For instance, this is a valid invocation to
process the file foo.htex verbosely: haskintex foo -verbose.
autotexy: Apply the function texy from the
Text.LaTeX.Base.Texy
module of the HaTeX package to every expression in a hatex or iohatex
command. This effectively allows the user to write expressions in types other than LaTeX
and have haskintex to perform the required transformation.
debug: Only for debugging purposes. It writes a file with extension .debughtex with the
AST of the internal representation of the input file haskintex uses.
help: Show the version of the program and some information, like usage and
a description of the different flags.
keep: Do not remove the auxiliary module after the program ends.
The name of the auxiliary module is the name of the input file preceded by Haskintex_.
lhs2tex: By default, haskintex uses basic LaTeX verb
and verbatim declarations for Haskell code. When this flag is enabled, the output
will be formatted for lhs2TeX.
manual: This flag will make haskintex write evalhaskell
and writehaskell outputs unchanged. In other words, no verb,
verbatim, or code (in case the lhs2tex flag is enabled) declarations
will be used.
memo: Unless otherwise specified, every evalhaskell, hatex
or iohatex command (or environment) will be called with the memo option.
memoclean: Cleans the memo tree after the execution of haskintex. If
several files are processed, the memo tree will be cleaned after processing all of
them. Read more about the memo tree in the Memorization section.
nosandbox: Do not use the sandbox package db even if haskintex is running
in one.
overwrite: Overwrite the output file if it already exists. If this flag
is not set, the program will ask before overwriting.
stdout: Instead of writing the final output to a file, send it to the standard
output stream (usually, the screen), making possible to redirect the output to another application.
verbose: While working, print information on the screen about the execution.
visible: Make Haskell code in writehaskell environments visible by default.
The code of haskintex is hosted on GitHub. For suggestions, bug reports, or any other concern, fill an issue at the Issue Tracker.