Literate Haskell support for Markdown
Pull request Compare This branch is 18 commits behind sol:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Literate Haskell support for Markdown

markdown-unlit is a custom unlit program. It can be used to extract Haskell code from Markdown files.

To use it with GHC, add

ghc-options: -pgmL markdown-unlit

to your cabal file.

Extended example

tl;dr markdown-unlit allows you to have a README.markdown, that at the same time is a literate Haskell program.

The following steps show you how to set things up, so that:

  • the Haskell code in your README.markdown gets syntax highlighted on GitHub
  • you can run your literate Haskell within GHCi
  • you can create a Cabal test-suite from your README.markdown (no broken code examples anymore, yay!)

The complete code of this example is provided in the example subdirectory.

1. Install markdown-unlit

$ cabal update && cabal install markdown-unlit

2. Create a README.markdown

# nifty-library: Do nifty things (effortlessly!)

Here is a basic example:

~~~ {.haskell}
main :: IO ()
main = putStrLn "That was easy!"

We use fenced code blocks here. They are supported by GitHub's README renderer, and many other software packages (e.g. Pandoc).

Code blocks with class .haskell are syntax highlighted on GitHub (like so).

3. Create a symbolic link README.lhs -> README.markdown

$ ln -s README.markdown README.lhs

4. Run yor code

At this point we can load the code into GHCi:

$ ghci -pgmL markdown-unlit README.lhs
*Main> main
That was easy!

Or better yet, pipe the required flag into a .ghci file, and forget about it:

$ echo ':set -pgmL markdown-unlit' > .ghci
$ ghci README.lhs
*Main> main
That was easy!

5. Create a Cabal test-suite

name:             nifty-library
version:          0.0.0
build-type:       Simple
cabal-version:    >= 1.8

  -- nothing here yet

test-suite readme
  type:           exitcode-stdio-1.0
  main-is:        README.lhs
  build-depends:  base
  ghc-options:    -pgmL markdown-unlit

Run it like so:

$ cabal configure --enable-tests && cabal build && cabal test


By default, markdown-unlit extracts all code that is marked with .haskell, unless it is marked with .ignore as well. You can customize this by passing -optL <pattern> to GHC.

A simple pattern is just a class name, e.g.:

-optL foo

extracts all code that is marked with .foo.

A class name can be negated by prepending it with a !, e.g.

-optL !foo

extracts all code, unless it is marked with .foo.

You can use + to combine two patterns with AND, e.g.

-optL foo+bar

extracts all code that is marked with both .foo and .bar.

If -optL is given multiple times, the patterns are combined with OR, e.g.

-optL foo -optL bar

extracts all code that is either marked with .foo or .bar.



  • indented code blocks are not yet supported
  • code blocks fenced with ``` are not yet supported
  • class names have to be enclosed in curly brackets, e.g. ~~~ .foo does not work

If you want to get any of those limitations lifted, open a ticket or send a pull request.


Add tests for new code, and make sure that the test suite passes with your modifications.

cabal configure --enable-tests && cabal build && cabal test

Real world examples

That's it, have fun!