Below are the five most recent posts in my weblog. You can also see a chronological list of all posts, dating back to 1999.

It's been more than a year since I wrote about Opinionated IkiWiki, a pre-configured, containerized deployment of Ikiwiki with opinions. My intention was to make something that is easy to get up and running if you are more experienced with containers than IkiWiki.

I haven't yet switched to Opinionated IkiWiki for this site, but that was my goal, and I think it's mature enough now that I can migrate over at some point, so it seems a good time to call it Version 1.0. I have been using it for my own private PIM systems for a while now.

You can pull built images from, here: The source lives here: A description of some of the changes made to the IkiWiki version lives here:


I'm writing up a PhD deliverable (which will show up here eventually) using LaTeX, which is my preferred tool for such things, since I also use it for papers, and will eventually be using it for my thesis itself. For this last document, I experimented with a few packages and techniques for organising the document which I found useful, so I thought I'd share them.

What version is this anyway?

I habitually store and develop my documents in git repositories. From time to time I generate a PDF and copy it off elsewhere to review (e.g., an iPad). Later on it can be useful to be able to figure out exactly what source built the PDF. I achieve this using

\newcommand{\version}{\input|"git describe --always --dirty"}

And \version\ somewhere in the header of the document.

Draft mode

The common document classes all accept a draft argument, to enable Draft Mode.


Various other packages behave differently if Draft Mode is enabled. The graphicx package, for example, doesn't actually draw pictures in draft mode, which I don't find useful. So for that package, I force it to behave as if we were in "Final Mode" at all times:


I want to also include some different bits and pieces in Draft Mode. Although the final version won't need it, I find having a Table of Contents very helpful during the writing process. The ifdraft package adds a convenience macro to query whether we are in draft or not. I use it like so:

This page will be cut from the final report.

For this document, I have been given the section headings I must use and the number of pages each section must run to. When drafting, I want to include the page budget in the section names (e.g. Background (2 pages)). I also force new pages at the beginning of each Section, to make it easier to see how close I am to each section's page budget.

\section{Work completed\ifdraft{ (1 page)}{}} % 1 Page


Two TODO items in the margin

Two TODO items in the margin

Collated TODOs in a list

Collated TODOs in a list

The todonotes package package is one of many that offers macros to make managing in-line TODO notes easier. Within the source of my document, I can add a TODO right next to the relevant text with \todo{something to do}. In the document, by default, this is rendered in the right-hand margin. With the right argument, the package will only render the notes in draft mode.


todonotes can also collate all the TODOs together into a single list. The list items are hyperlinked back to the page where the relevant item appears.

  This page will be cut from the final report.

Last year I began looking at queuing theory, to try and see if I could use it as a robust underpinning for a cost model to evaluate rewritten stream-processing programs.

I started to work with my co-supervisor, Dr. Paul Ezhilchelvan, who is an expert in this area. In order to brief him on the work I'd done so far as well as my initial efforts to map queueing theory concepts onto Striot's concepts, I prepared a brief presentation:


The UBI OpenJDK containers are full fat developer containers: they've got the full OpenJDK distribution in them (including javac etc.); they include Maven and there are various quality-of-life additions such as a Prometheus agent for metrics gathering in OpenShift and a run-java script to control launching the eventual application, as well as OpenShift Source-To-Image (S2I) integration.

We've had a number of customers request that we produce some runtime-only images. It took a while to properly scope the request, as each person who wanted such a thing wanted a different subset of functionality included from the existing images. One consistent request though related to image size: It became clear that the runtime images should be as minimal as possible.

Last week we launched ubi8/openjdk-8-runtime and ubi8/openjdk-11-runtime containers which weight in at 106.M1iB and 119.7 MiB respectively. They are extremely bare-bones, containing just a subset of the OpenJDK distribution (that which is packaged as java-N-openjdk-headless in RHEL) on top of the UBI minimal flavour base images.

To explain one way these could be use in an OpenShift environment I wrote a blog post for Red Hat Developer: Build lean Java containers with the new Red Hat Universal Base Images OpenJDK runtime images.

We've got a couple of avenues under exploration in this area which should result in even leaner or more tailored images in the future. I'll write more when we have something to show!


A couple of weeks ago I stumbled across a Template Haskell question on the Haskell sub-reddit. This was quite exciting because I rarely see TH questions, and this one was by someone working on something which was quite similar to what I had done: they were writing a code generator, and had pure functions of type Exp -> Exp -> Exp, but wanted to leverage TH's quasi-quotation syntax (e.g. [| \p -> p + 1 |]) as a syntactic short-hand. Alas these quasi-quotes are of type Q Exp, so the question becomes, how to escape Q?

I had to do exactly this, so I knew an answer: use unsafePerformIO. Another commenter pointed at this Overloaded Quotation Brackets GHC Proposal which I was not aware of and is a much more elegant solution, available since GHC 9.0.1.

There was something odd about the question, though.

Sometime later on, I checked back to find that the thread had been deleted. It turns out it was one of a set of duplicate posts with exactly the same question. Spammers are copying old questions and reposting them, presumably in an attempt to harvest "Reddit karma".

When I learned that, my sense of oddness about the question remained, so I went to find the original thread, to discover I wrote the original question a year ago and had therefore literally answered my own question a year later.

Back to the more elegant solution. In GHC versions 9 onwards, quasi-quotation returns a different type that is not bound up in the Q Monad:

GHC 8.8.4:

λ> :t [| 42 |]
[| 42 |] :: Language.Haskell.TH.Lib.Internal.ExpQ
λ> [| 42 |]

<interactive>:5:1: error:
    • No instance for (Show Language.Haskell.TH.Lib.Internal.ExpQ)
        arising from a use of ‘print’
    • In a stmt of an interactive GHCi command: print it

GHC 9.0.1:

λ> :t [| 42 |]
[| 42 |]
  :: Language.Haskell.TH.Syntax.Quote m =>
     m Language.Haskell.TH.Syntax.Exp
λ> [| 42 |]
LitE (IntegerL 42)

Older posts are available on the all posts page.