# IHaskell: a Haskell kernel for Jupyter notebooks

> IHaskell puts GHC inside Jupyter frontends, so cells evaluate Haskell expressions and render typed results. It is a build-toolchain project first: expect Cabal or Stack, system libraries for ZeroMQ, Cairo and Pango, and a kernel registration step before anything runs.

**IHaskell/IHaskell** — A Haskell kernel for the Jupyter project.

- Repository: https://github.com/IHaskell/IHaskell
- Stars: 2,660 · Forks: 267
- Language: Jupyter Notebook
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/ihaskell-ihaskell

## What IHaskell adds to a Jupyter installation

Jupyter frontends talk to a kernel over a wire protocol, and each language supplies its own kernel process. IHaskell is that process for Haskell. The README describes it as "a kernel for the Jupyter project, which allows you to use Haskell inside Jupyter frontends (including the console and notebook)", and it currently supports GHC 8.4 through 9.14 inclusive.

The audience is narrow and specific. You need an existing Haskell toolchain, because the kernel is a compiled Haskell executable that links against your GHC installation. Data scientists who want pandas-style convenience will find the setup heavier than they expect. The people who get value here are Haskell developers who want to keep a session alive while they explore a library, write a literate notebook, or hand a runnable example to someone else. A notebook also gives you a place to keep type errors and intermediate values next to the code, which a batch compile does not.

The project is not archived, and the last push was on 2026-08-15. That is recent enough that the repository is being touched, but the README itself does not describe a release cadence or a support window, so the GHC range is the support statement you actually have.

## How the kernel, parser and display packages fit together

The repository layout shows the split clearly. Top-level directories include ipython-kernel, ghc-parser, ihaskell-display, jupyterlab-ihaskell, src, main, html and notebooks. The name ipython-kernel is the giveaway: the Jupyter messaging protocol is implemented as its own package rather than buried inside the executable. ghc-parser is a separate package too, which means the code that turns a cell into something GHC can evaluate is reusable outside the kernel.

ihaskell-display holds the rendering modules. The README notes that under Nix these "are not loaded by default and have to be specified separately", with nix build .#ihaskell-env-display-ghc98 as an example. That is the mechanism behind rich output: the kernel evaluates a cell, the display modules decide how a value becomes HTML, an image or plain text, and the frontend renders it. If the display modules are absent, you still get evaluation, but not the rendering layer.

jupyterlab-ihaskell is a JupyterLab extension directory, and html holds static assets. The Dockerfile confirms the same dependency chain from the build side: it copies ipython-kernel, ghc-parser and ihaskell-display before running stack build ihaskell --only-snapshot, then copies src, html, main and jupyterlab-ihaskell before stack install ihaskell. Two stages, because the package dependencies change rarely and the kernel source changes often.

## Installing IHaskell with Cabal and registering the kernel

The README starts with ghcup for Haskell itself, then lists system prerequisites that differ per platform. On Linux the package list is long: python3-pip, git, libtinfo-dev, libzmq3-dev, libcairo2-dev, libpango1.0-dev, libmagic-dev, libblas-dev and liblapack-dev. On macOS it is brew install python3 zeromq libmagic cairo pkg-config pango, plus the Xcode command line tools via xcode-select --install. Windows uses Clang64 MSYS2 packages. Jupyter itself comes from pip3 install jupyter.

With the toolchain in place, the Cabal path is two steps. First the executable:

```bash
cabal install ihaskell
```

Then the kernel installation, which is where most first attempts go wrong. The README's command passes the GHC library directory explicitly and sets a prefix:

```bash
ihaskell install --ghclib=$(ghc --print-libdir) --prefix=$HOME/.local/
```

That writes a kernel specification under $HOME/.local/share/jupyter/kernels/haskell/. Registering it with Jupyter is a separate command:

```bash
jupyter kernelspec install $HOME/.local/share/jupyter/kernels/haskell/
```

Run jupyter kernelspec list to confirm. The README says you should see a Haskell kernel installed, after which jupyter notebook starts as usual. The two-step split matters: editors such as VS Code can select the kernel directly from its installed location without the kernelspec registration, which is why the README presents registration as the manual option rather than the only one.

## Stack, Docker and Nix routes, and the stack.yaml requirement

The Stack route bundles the Jupyter invocation into the same environment. The README's sequence clones the repository, installs Python requirements, runs stack install --fast, then ihaskell install --stack, and finally starts the frontend through Stack itself:

```bash
stack exec jupyter -- notebook
```

Stack keeps a separate environment per package, and the troubleshooting section is blunt about the consequence: "By default your notebooks will only have access to a few packages that happen to be required for IHaskell." To use another library you add it to the packages: section of the IHaskell directory's stack.yaml and run stack install --fast again. That is a real workflow constraint, not a footnote.

The Docker route avoids the local toolchain entirely. The README gives docker build -t ihaskell:latest . followed by docker run --rm -p 8888:8888 ihaskell:latest, or the continuously updated image on Docker Hub. Mounting local files uses -v "$PWD":/home/jovyan/src, and the README states the mounted directory must contain a stack.yaml file, with a minimal example of resolver: lts-16.23 and packages: []. It recommends matching the LTS version the image itself uses, because otherwise Stack installs GHC inside the container before your notebook starts.

Nix is the shortest path when flakes are enabled. The README shows nix build, then running bin/jupyter notebook from the result path, with the ihaskell.cachix.org cache for prebuilt artifacts. The first build takes a while; later ones do not.

## Where IHaskell is the wrong tool

The GHC version range is the first hard boundary. GHC 8.4 through 9.14 is what the README claims. If your codebase is pinned to an older compiler, IHaskell is not an option, and upgrading the compiler to get a notebook is the wrong order of operations.

The Stack package isolation is the second. A notebook that imports a library you have not added to stack.yaml will fail to import it, and the fix is a rebuild, not a cell edit. That makes IHaskell a poor fit for quick evaluation of an unfamiliar package. A plain ghci session with stack ghci or cabal repl has the same package model but no kernel registration step, no Jupyter frontend, and no rebuild of the kernel executable when you change the environment.

There is also a dependency weight problem. The system prerequisites include ZeroMQ, Cairo, Pango, libmagic and BLAS/LAPACK. On a machine where you cannot install system packages, or on a managed CI runner with a minimal image, the Docker image is the practical answer and a local install is not. The README does not document an uninstall procedure or a rollback path for ihaskell install, so if you register the kernel into a shared Jupyter installation, removing it is on you through the kernelspec tooling.

## IHaskell compared with a plain GHCi session

The honest alternative is ghci, the interpreter shipped with GHC. Both evaluate Haskell expressions against an installed package set, and both keep state between inputs. The difference is what surrounds the evaluator. GHCi is a terminal program: output is text, history is whatever your shell gives you, and sharing a session means copying text out. IHaskell implements the Jupyter messaging protocol in the ipython-kernel package, so the same session can be driven by the notebook, the console frontend, or an editor that speaks the protocol. Cells persist, outputs are stored in the notebook file, and the display packages can turn a value into something richer than a printed string.

What you give up is immediacy. GHCi starts in the environment you already have. IHaskell needs a compiled executable, a kernel specification on disk, and in the Stack case a rebuild whenever the package set changes. For a five-minute type check, GHCi wins. For a document that someone else will open and run, the notebook format is the point. The README points to a demo notebook and a wiki of examples, which is the intended way to see the difference before installing anything.

## Maintenance, licensing and what a version bump costs

IHaskell is MIT licensed, which is permissive and places few obligations on how you redistribute a notebook or a container built from the repository. The Dockerfile copies LICENSE into the build stage, so images built from it carry the licence file. Questions about combining MIT code with other licences in your own distribution are for your own review, not something the README answers.

The maintenance cost is dominated by the GHC range. The README has a Developing section stating that IHaskell is updated to work with the latest version of GHC, and links a blog post describing how that is done. The practical reading is that a GHC upgrade in your project can require a matching IHaskell build, and the Stack route ties the two together through the resolver. The Dockerfile pins ARG GHC_VERSION=9.6.7 with a comment that it should match the GHC version of the stack.yaml resolver checked in CI, which tells you the project tracks that pairing deliberately.

No tagged releases appear in the repository listing, so there is no versioned changelog to consult. The last push was on 2026-08-15. If your adoption depends on a stable tagged artifact, that is something to confirm against the repository itself rather than assume.

## Conclusion

IHaskell is for people who already have a working GHC toolchain and want Haskell cells in a notebook, either through Cabal, Stack, Docker or Nix. It is the wrong choice if you want a zero-setup REPL, if your project is pinned to a GHC older than 8.4 or newer than 9.14, or if you cannot install the system libraries for ZeroMQ, Cairo and Pango. Before committing, verify that the GHC version you use falls inside the supported range, and check whether the display modules you want are loaded by default: the README states that under Nix they are not, and must be requested separately, for example with nix build .#ihaskell-env-display-ghc98.

## FAQ

### Which GHC versions does IHaskell support?

The README states that IHaskell currently supports GHC 8.4 through 9.14 inclusive. Anything outside that range is not covered by the project's own support statement.

### How do I install the IHaskell kernel for Jupyter?

After installing the ihaskell executable, run ihaskell install --ghclib=$(ghc --print-libdir) --prefix=$HOME/.local/ and then register it with jupyter kernelspec install $HOME/.local/share/jupyter/kernels/haskell/. Confirm with jupyter kernelspec list, which should show a Haskell kernel.

### Can I run IHaskell in Docker?

Yes. The README gives docker build -t ihaskell:latest . followed by docker run --rm -p 8888:8888 ihaskell:latest, or the continuously updated gibiansky/ihaskell image on Docker Hub. If you mount a local directory with -v, that directory must contain a stack.yaml file.

### Why can't my IHaskell notebook find a package I installed?

Under Stack, notebooks only see the packages required by IHaskell unless you add others to the packages: section of the IHaskell directory's stack.yaml and run stack install --fast again. Stack keeps a separate environment per package, so a package installed elsewhere is not visible.

### Are the IHaskell display modules loaded by default?

The README states that the display modules are not loaded by default under Nix and have to be specified separately, giving nix build .#ihaskell-env-display-ghc98 as an example.

## Sources

- [IHaskell/IHaskell on GitHub](https://github.com/IHaskell/IHaskell)
- [Issues](https://github.com/IHaskell/IHaskell/issues)
- [License: MIT](https://github.com/IHaskell/IHaskell/blob/master/LICENSE)
- [README](https://github.com/IHaskell/IHaskell/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ihaskell-ihaskell
