# Typst-Unlit *[tangled.org/@oppi.li/typst-unlit](https://tangled.org/@oppi.li/typst-unlit)* *Serves: 1 Prep Time: 10min Compile Time: 10ms* A literate program is one where comments are first-class citizens, and code is explicitly demarcated, as opposed to a regular program, where comments are explicitly marked, and code is a first-class entity. GHC supports literate programming out of the box, by using a preprocessor to extract code from documents. This preprocessor is known as *unlit*[^1]. GHC also supports *custom* preprocessors, which can be passed in via the `-pgmL` flag. This very document you are reading, is one such preprocessor that allows embedding Haskell code inside typst files[^2]. This recipe not only gives you a fish (the typst-unlit preprocessor), but also, teaches you how to fish (write your own preprocessors). ## Ingredients

To write your own preprocessor:

  • GHC: the Glorious Haskell Compiler
  • Typst: to generate PDFs
  • And thats it! No stacking, shaking or caballing here.

To compile this very document:

  • The bootstrap program
  • GHC: to produce an executable program
  • Typst: to produce a readable PDF
**Pro Tip:** If you’re missing any ingredients, your local nixpkgs should stock them! ## Instructions The idea behind the unlit program is super simple: iterate over the lines in the supplied input file and replace lines that aren’t Haskell with an empty line! To detect lines that are Haskell, we look for the ```` ```haskell ```` directive and stop at the end of the code fence. Simple enough! Annoyingly, Haskell requires that imports be declared at the top of the file. This results in literate haskell programs always starting with a giant block of imports: > -- So first we need to get some boilerplate and imports out of the way. — Every literate programmer Oh gee, if only we had a tool to put the important stuff first. Our preprocessor will remedy this wart, with the `haskell-top` directive to move blocks to the top. With that out of the way, lets move onto the program itself! ### Step 1: The maincourse I prefer starting with `main` but you do you. Any program that is passed to `ghc -pgmL` has to accept exactly 4 arguments: - `-h`: ignore this for now - `