Write slides with literate Haskell and LaTeX Beamer

How to take the best of both worlds without pain.

Published on November 15, 2018 under the tag latex, beamer, haskell, literate programming

Introduction

TL;DR: Check this GitHub Repository and enjoy writing :)

Literate programming, introduced by Donald Knuth1, is a programming paradigm where source code is written interleaved with text in natural language in a way that it is both a valid document (for example, article) and compilable (or interpretable) program.

If you are familiar with Doxygen or Sphinx which generate documentation from the comments of source code, you can consider literate programming as the opposite: it is the source code in documentation. The idea behind is best explained by Knuth’s own words

“The main idea is to regard a program as a communication to human beings rather than as a set of instructions to a computer.”

Literate programming in Haskell

If you are data scientist like me, you must be familiar with Jupyter Notebook where we can write Markdown or even LaTeX snippet along with Python2 (or many others through kernels) code. So basically you are using literate programming everyday!

However, I personally find two inconveniences with Jupyter

Haskell, on the other hand, is one of the few languages that support literate programming natively. In other words, files written in literate Haskell can be compiled directly with GHC or loaded into GHCi.

Instead of the normal .hs extension, a literate program ends with .lhs where l means literate (surprise!). To tell GHC a portion of text is code, we have two options

Here are two examples3

In Bird-style you have to leave a blank before the code.
 
> fact :: Integer -> Integer
> fact 0 = 1
> fact n = n * fact (n-1)
 
And you have to leave a blank line after the code as well.
In LaTeX style, the code snippet must be at the top indentation level
or you will have an `unlit' error
\begin{code}
tsort []     = []
tsort (x:xs) = tsort [y | y<-xs, y>x] ++ [x] ++ tsort [y | y<-xs, y<=x]
\end{code}

It seems that the LaTeX style is more robust, so you should privilege it whenever possible.

As to the non-code portions, Haskell is rather agnostic so you can write LaTeX, HTML or whatever you want. But be careful, however, if you write Markdown

Write slides with literate Haskell

Since in literate Haskell we have very few restraints on writing non-code text, we can actually write slides!

Javascript-based approach

A number of Javascript based libraries such as reveal.js make it possible to produce attractive slides with HTML or Markdown sources. However, it is not easy (if possible at all) to write a literate Haskell which gets highlighted correctly in the rendered HTML output. It is even more difficult to hide valid code in the slides or hide invalid code from Haskell.

One possible solution is to use Pandoc as a middleware when render the HTML. For example, it can output reveal.js HTML from Markdown source. However, since we cannot use #, ## to mark levels, the output HTMLs have very shallow structure.

LaTeX beamer

The best solution I found is to simply use LaTeX beamer. For those who are not familiar with it, it is a LaTeX package which are widely used to produce academic slides. Since literate Haskell supports LaTeX mode, we have full control over the output slides.

Only a few pitfalls here

Here is a minimalist template

% filename: main.lhs
\documentclass{beamer}

\usepackage{minted}
\newenvironment{code}{\VerbatimEnvironment\begin{minted}{haskell}}{\end{minted}}
\newenvironment{spec}{\VerbatimEnvironment\begin{minted}{haskell}}{\end{minted}}

\newenvironment{slide}[1]
  {\begin{frame}[fragile,environment=slide]{#1}}
  {\end{frame}}
\long\def\ignore#1{}

\title{Title}
\subtitle{Subtitle}
\author{Author}
\date{\today}

\begin{document}

\begin{slide}{Example}
This appear both in slides and Haskell
\begin{code}
add :: Integer -> Integer -> Integer
add x y =  x + y
\end{code}
This only appear in slides
\begin{spec}
-- broken code
foo :: String
foo = bar
\end{spec}
And this only appear in Haskell
\ignore{
\begin{code}
module Main where

import Control.Applicative
\end{code}
}
\end{slide}

\end{document}

  1. Knuth wrote the TeX engine, which powers document preparation systems like LaTeX, XeLaTeX and many more, in literate Pascal called WEB.

  2. If you prefer using R, R Notebook looks great too.

  3. It is not recommended to mix these two styles, otherwise you will get some mysterious parse errors.