From 9f57e2c52e3f186ad6fdf2b8538f660299ad98a8 Mon Sep 17 00:00:00 2001
From: Tom McLaughlin <tom@codedown.io>
Date: Sat, 8 Jul 2023 01:39:10 -0700
Subject: [PATCH] Nix and stack.yaml organization

---
 .github/workflows/ci.yml                      | 108 ----------
 .github/workflows/docker.yml                  |  75 +++----
 .github/workflows/nix.yml                     |  95 +++++----
 .github/workflows/stack.yml                   | 103 ++++++++++
 Dockerfile                                    |   2 +-
 flake.lock                                    | 139 +++++++------
 flake.nix                                     | 184 ++++++++----------
 .../IHaskell/Display/Widgets/Singletons.hs    |   2 +-
 .../src/IHaskell/Display/Widgets/Types.hs     |   8 +-
 nix/displays.nix                              |  15 ++
 nix/ihaskell-overlay.nix                      |  41 ++++
 nix/ihaskell-src.nix                          |  19 ++
 nix/mkDevShell.nix                            |  40 ++++
 nix/overlay-8.10.nix                          |  16 ++
 nix/overlay-9.0.nix                           |  13 ++
 nix/overlay-9.4.nix                           |  20 ++
 nix/overlay-9.6.nix                           |  35 ++++
 nix/overlay-9.8.nix                           |  64 ++++++
 nix/release.nix                               | 109 +++++++++++
 release-9.2.nix                               |   9 -
 release-9.4.nix                               | 122 ------------
 release-9.6.nix                               |  35 ----
 release-9.8.nix                               | 166 ----------------
 release.nix                                   | 105 ----------
 stack-8.2.yaml                                |  62 ------
 stack-8.4.yaml                                |  49 -----
 stack-8.6.yaml                                |  48 -----
 stack-8.8.yaml                                |  50 -----
 stack-9.0.yaml                                |  48 -----
 stack-9.2.yaml                                |  40 ----
 stack.yaml                                    |  88 ++++-----
 stack-8.0.yaml => stack/stack-8.0.yaml        |  23 ++-
 stack-8.10.yaml => stack/stack-8.10.yaml      |  53 +++--
 stack/stack-8.10.yaml.lock                    | 138 +++++++++++++
 stack/stack-8.2.yaml                          |  61 ++++++
 stack/stack-8.2.yaml.lock                     | 103 ++++++++++
 stack/stack-8.4.yaml                          |  48 +++++
 stack/stack-8.4.yaml.lock                     |  40 ++++
 stack/stack-8.6.yaml                          |  47 +++++
 stack/stack-8.6.yaml.lock                     |  61 ++++++
 stack/stack-8.8.yaml                          |  49 +++++
 stack/stack-8.8.yaml.lock                     |  75 +++++++
 stack/stack-9.0.yaml                          |  47 +++++
 stack/stack-9.0.yaml.lock                     |  61 ++++++
 stack/stack-9.2.yaml                          |  38 ++++
 stack/stack-9.2.yaml.lock                     |  12 ++
 stack/stack-9.4.yaml                          |  51 +++++
 stack/stack-9.4.yaml.lock                     |  19 ++
 stack/stack-9.6.yaml                          |  55 ++++++
 stack/stack-9.6.yaml.lock                     |  23 +++
 50 files changed, 1732 insertions(+), 1182 deletions(-)
 delete mode 100644 .github/workflows/ci.yml
 create mode 100644 .github/workflows/stack.yml
 create mode 100644 nix/displays.nix
 create mode 100644 nix/ihaskell-overlay.nix
 create mode 100644 nix/ihaskell-src.nix
 create mode 100644 nix/mkDevShell.nix
 create mode 100644 nix/overlay-8.10.nix
 create mode 100644 nix/overlay-9.0.nix
 create mode 100644 nix/overlay-9.4.nix
 create mode 100644 nix/overlay-9.6.nix
 create mode 100644 nix/overlay-9.8.nix
 create mode 100644 nix/release.nix
 delete mode 100644 release-9.2.nix
 delete mode 100644 release-9.4.nix
 delete mode 100644 release-9.6.nix
 delete mode 100644 release-9.8.nix
 delete mode 100644 release.nix
 delete mode 100644 stack-8.2.yaml
 delete mode 100644 stack-8.4.yaml
 delete mode 100644 stack-8.6.yaml
 delete mode 100644 stack-8.8.yaml
 delete mode 100644 stack-9.0.yaml
 delete mode 100644 stack-9.2.yaml
 rename stack-8.0.yaml => stack/stack-8.0.yaml (82%)
 rename stack-8.10.yaml => stack/stack-8.10.yaml (51%)
 create mode 100644 stack/stack-8.10.yaml.lock
 create mode 100644 stack/stack-8.2.yaml
 create mode 100644 stack/stack-8.2.yaml.lock
 create mode 100644 stack/stack-8.4.yaml
 create mode 100644 stack/stack-8.4.yaml.lock
 create mode 100644 stack/stack-8.6.yaml
 create mode 100644 stack/stack-8.6.yaml.lock
 create mode 100644 stack/stack-8.8.yaml
 create mode 100644 stack/stack-8.8.yaml.lock
 create mode 100644 stack/stack-9.0.yaml
 create mode 100644 stack/stack-9.0.yaml.lock
 create mode 100644 stack/stack-9.2.yaml
 create mode 100644 stack/stack-9.2.yaml.lock
 create mode 100644 stack/stack-9.4.yaml
 create mode 100644 stack/stack-9.4.yaml.lock
 create mode 100644 stack/stack-9.6.yaml
 create mode 100644 stack/stack-9.6.yaml.lock

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index 0c1d153d..00000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,108 +0,0 @@
-name: CI
-
-on:
-  push:
-    branches:
-      - master
-    paths-ignore:
-      - 'demo/**'
-      - 'docker/**'
-      - 'Dockerfile'
-      - '.dockerignore'
-      - '.ghci'
-      - '.gitignore'
-      - 'images/**'
-      - 'notebooks/**'
-      - 'README.md'
-      - 'hie.yaml'
-      - '*.nix'
-  pull_request:
-    paths-ignore:
-      - 'demo/**'
-      - 'docker/**'
-      - 'Dockerfile'
-      - '.dockerignore'
-      - '.ghci'
-      - '.gitignore'
-      - 'images/**'
-      - 'notebooks/**'
-      - 'README.md'
-      - 'hie.yaml'
-      - '*.nix'
-
-jobs:
-  linux:
-    runs-on: ubuntu-20.04
-    strategy:
-      fail-fast: false
-      matrix:
-        versions:
-          - stack-yaml: 'stack-8.0.yaml'
-          - stack-yaml: 'stack-8.2.yaml'
-          - stack-yaml: 'stack-8.4.yaml'
-          - stack-yaml: 'stack-8.6.yaml'
-          - stack-yaml: 'stack-8.8.yaml'
-          - stack-yaml: 'stack-8.10.yaml'
-          - stack-yaml: 'stack-9.0.yaml'
-          - stack-yaml: 'stack-9.2.yaml'
-          - stack-yaml: 'stack.yaml'
-
-    steps:
-      - uses: actions/checkout@v2
-      - name: Cache .stack
-        uses: actions/cache@v2.1.6
-        with:
-          path: ~/.stack/snapshots
-          key: ${{ runner.os }}-${{ matrix.versions.stack-yaml }}-${{ hashFiles(format('./{0}', matrix.versions.stack-yaml)) }}
-          restore-keys: |
-            ${{ runner.os }}-${{ matrix.versions.stack-yaml }}
-      - name: Update system dependencies
-        run: |
-          sudo apt update
-      - name: Install system dependencies
-        run: |
-          sudo apt install libmagic-dev libgmp-dev libblas-dev liblapack-dev libcairo2-dev libpango1.0-dev libzmq3-dev jq
-      - name: Set up Python
-        uses: actions/setup-python@v1
-        with:
-          python-version: '3.8'
-      - name: Install Python dependencies
-        run: |
-          python -m pip install --upgrade pip setuptools wheel
-          pip install -r requirements.txt
-      - name: Install Stack
-        run: |
-          export PATH=$HOME/.local/bin:$PATH
-          mkdir -p ~/.local/bin
-          curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
-      - name: Build dependencies
-        run: |
-          # Used to avoid 'source and destination file are the same' error
-          mv ${{ matrix.versions.stack-yaml }} intermediate-stack.yaml
-          mv intermediate-stack.yaml stack.yaml
-
-          echo "apply-ghc-options: everything" >> stack.yaml
-
-          stack setup
-          stack install gtk2hs-buildtools
-          stack build hmatrix
-          stack build --dependencies-only
-      - name: Run Haskell tests
-        run: |
-          set -e
-          stack build ipython-kernel --flag ipython-kernel:examples
-          stack test ihaskell --no-terminal
-      - name: Run integration test
-        # The test is flaky on GHC 8.0 so we don't run it. As long as the tests
-        # above pass, it's unlikely that we'll introduce a bug that we will
-        # only catch through the integration test on this version and not other
-        # versions.
-        if: ${{ !contains(fromJSON('["stack-8.0.yaml", "stack-8.2.yaml"]'), matrix.versions.stack-yaml) }}
-        run: |
-          set -e
-          stack build --no-terminal
-          # Ensure that IHaskell notebook remains unchanged.
-          # Run the notebook to regenerate the outputs, then compare the new notebook to the old one.
-          stack install
-          stack exec -- ihaskell install --stack
-          test/acceptance.nbconvert.sh stack exec -- jupyter nbconvert
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 9730c5a2..294e08c1 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -1,48 +1,54 @@
-name: "Docker"
+name: Docker
+
 on:
   push:
     branches:
-      - master
     paths:
-      - '.dockerignore'
-      - '.github/workflows/docker.yml'
-      - 'Dockerfile'
-      - 'LICENSE'
-      - 'ghc-parser/**'
-      - 'html/**'
-      - 'ihaskell-display/**'
-      - 'ihaskell.cabal'
-      - 'ipython-kernel/**'
-      - 'jupyterlab-ihaskell/**'
-      - 'main/**'
-      - 'src/**'
-      - 'stack.yaml'
+    - '.dockerignore'
+    - '.github/workflows/docker.yml'
+    - 'Dockerfile'
+    - 'LICENSE'
+    - 'ghc-parser/**'
+    - 'html/**'
+    - 'ihaskell-display/**'
+    - 'ihaskell.cabal'
+    - 'ipython-kernel/**'
+    - 'jupyterlab-ihaskell/**'
+    - 'main/**'
+    - 'src/**'
+    - 'stack.yaml'
   pull_request:
     paths:
-      - '.dockerignore'
-      - '.github/workflows/docker.yml'
-      - 'Dockerfile'
-      - 'LICENSE'
-      - 'ghc-parser/**'
-      - 'html/**'
-      - 'ihaskell-display/**'
-      - 'ihaskell.cabal'
-      - 'ipython-kernel/**'
-      - 'jupyterlab-ihaskell/**'
-      - 'main/**'
-      - 'src/**'
-      - 'stack.yaml'
+    - '.dockerignore'
+    - '.github/workflows/docker.yml'
+    - 'Dockerfile'
+    - 'LICENSE'
+    - 'ghc-parser/**'
+    - 'html/**'
+    - 'ihaskell-display/**'
+    - 'ihaskell.cabal'
+    - 'ipython-kernel/**'
+    - 'jupyterlab-ihaskell/**'
+    - 'main/**'
+    - 'src/**'
+    - 'stack.yaml'
 
 jobs:
   build:
     runs-on: ubuntu-latest
+
+    strategy:
+      fail-fast: false
+
     steps:
-    - uses: actions/checkout@v2
-    - name: Install Stack
-      run: |
-        export PATH=$HOME/.local/bin:$PATH
-        mkdir -p ~/.local/bin
-        curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
+    - uses: actions/checkout@v3
+
+    - uses: haskell/actions/setup@v2
+      name: Setup Haskell Stack
+      with:
+        enable-stack: true
+        stack-version: "latest"
+
     - name: Check Dockerfile GHC version matches
       run: |
         set -e
@@ -53,6 +59,7 @@ jobs:
           echo "GHC_VERSION should be ${STACK_GHC_VERSION}"
           exit 1
         fi
+
     - uses: elgohr/Publish-Docker-Github-Action@v5
       with:
         name: gibiansky/ihaskell
diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml
index 5db12273..47511e03 100644
--- a/.github/workflows/nix.yml
+++ b/.github/workflows/nix.yml
@@ -1,61 +1,72 @@
-name: "Nix"
+name: Nix
+
 on:
   schedule:
-    - cron: '0 2 * * *'
+  - cron: '0 2 * * *'
   push:
-    branches:
-      - master
     paths-ignore:
-      - 'demo/**'
-      - 'docker/**'
-      - 'Dockerfile'
-      - '.dockerignore'
-      - '.ghci'
-      - '.gitignore'
-      - 'images/**'
-      - 'notebooks/**'
-      - 'README.md'
-      - '*.yaml'
+    - 'demo/**'
+    - 'docker/**'
+    - 'Dockerfile'
+    - '.dockerignore'
+    - '.ghci'
+    - '.gitignore'
+    - 'images/**'
+    - 'notebooks/**'
+    - 'README.md'
+    - '*.yaml'
   pull_request:
     paths-ignore:
-      - 'demo/**'
-      - 'docker/**'
-      - 'Dockerfile'
-      - '.dockerignore'
-      - '.ghci'
-      - '.gitignore'
-      - 'images/**'
-      - 'notebooks/**'
-      - 'README.md'
-      - '*.yaml'
+    - 'demo/**'
+    - 'docker/**'
+    - 'Dockerfile'
+    - '.dockerignore'
+    - '.ghci'
+    - '.gitignore'
+    - 'images/**'
+    - 'notebooks/**'
+    - 'README.md'
+    - '*.yaml'
+
 jobs:
   build:
     runs-on: ubuntu-latest
     strategy:
+      fail-fast: false
       matrix:
-        versions:
-          - release: 'release-9.2.nix'
-          - release: 'release-9.4.nix'
-          - release: 'release-9.6.nix'
-          - release: 'release-9.8.nix'
+        env:
+        - ihaskell-env-ghc810
+        - ihaskell-env-ghc90
+        - ihaskell-env-ghc92
+        - ihaskell-env-ghc94
+        - ihaskell-env-ghc96
+        - ihaskell-env-ghc98
+
+        - ihaskell-env-display-ghc810
+        - ihaskell-env-display-ghc90
+        - ihaskell-env-display-ghc92
+        - ihaskell-env-display-ghc94
+        - ihaskell-env-display-ghc96
+        - ihaskell-env-display-ghc98
+
     steps:
-    - uses: actions/checkout@v2
-    - uses: cachix/install-nix-action@v20
+    - uses: actions/checkout@v3
+
+    - uses: cachix/install-nix-action@v22
       with:
         install_url: https://releases.nixos.org/nix/nix-2.13.3/install
+
     - uses: cachix/cachix-action@v12
       with:
         name: ihaskell
         signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
-    - run: |
-        nix-build --keep-going \
-        -I nixpkgs=https://github.com/NixOS/nixpkgs/tarball/nixos-23.05 \
-        ${{ matrix.versions.release }} \
-        --arg packages "haskellPackages: [ haskellPackages.ihaskell ]"
-    - if: matrix.versions.release != 'release-9.8.nix'
-      run: |
-        nix-shell \
-        -I nixpkgs=https://github.com/NixOS/nixpkgs/tarball/nixos-23.05 \
-        -p jq --run \
-        'test/acceptance.nbconvert.sh result/bin/jupyter nbconvert'
 
+    - name: Build environment ${{matrix.env}}
+      run: |
+        nix build .#${{matrix.env}}
+
+    - name: Check acceptance test for ${{matrix.env}}
+      # Disable GHC 9.8 here since we don't have hlint support yet
+      if: ${{ !contains(fromJSON('["ihaskell-env-ghc98"]'), matrix.env) && !contains(matrix.env, fromJSON('"display"')) }}
+      run: |
+        nix build .#checks.x86_64-linux.${{matrix.env}} -L
diff --git a/.github/workflows/stack.yml b/.github/workflows/stack.yml
new file mode 100644
index 00000000..0a1b9923
--- /dev/null
+++ b/.github/workflows/stack.yml
@@ -0,0 +1,103 @@
+name: Stack
+
+on:
+  push:
+    paths-ignore:
+    - 'demo/**'
+    - 'docker/**'
+    - 'Dockerfile'
+    - '.dockerignore'
+    - '.ghci'
+    - '.gitignore'
+    - 'images/**'
+    - 'notebooks/**'
+    - 'README.md'
+    - 'hie.yaml'
+  pull_request:
+    paths-ignore:
+    - 'demo/**'
+    - 'docker/**'
+    - 'Dockerfile'
+    - '.dockerignore'
+    - '.ghci'
+    - '.gitignore'
+    - 'images/**'
+    - 'notebooks/**'
+    - 'README.md'
+    - 'hie.yaml'
+
+jobs:
+  linux:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        stack-yaml:
+        # - 'stack/stack-8.2.yaml'
+        # - 'stack/stack-8.4.yaml'
+        # - 'stack/stack-8.6.yaml'
+        - 'stack/stack-8.8.yaml'
+        - 'stack/stack-8.10.yaml'
+        - 'stack/stack-9.0.yaml'
+        - 'stack/stack-9.2.yaml'
+        - 'stack/stack-9.4.yaml'
+        - 'stack/stack-9.6.yaml'
+        - 'stack.yaml'
+
+    steps:
+    - uses: actions/checkout@v3
+
+    - uses: cachix/install-nix-action@v22
+      with:
+        install_url: https://releases.nixos.org/nix/nix-2.13.3/install
+
+    - uses: haskell/actions/setup@v2
+      name: Setup Haskell Stack
+      with:
+        enable-stack: true
+        stack-version: "latest"
+
+    - uses: actions/cache@v3
+      name: Cache ~/.stack
+      with:
+        path: ~/.stack
+        key: ${{ runner.os }}-${{ matrix.stack-yaml }}-${{ hashFiles(format('./{0}', matrix.stack-yaml)) }}
+
+    - name: Build
+      run: |
+        export "NIX_PATH=nixpkgs=$(nix run .#print-nixpkgs-master)"
+        stack build --nix --stack-yaml ${{matrix.stack-yaml}}
+
+    - name: Test
+      if: ${{ !contains(fromJSON('["stack/stack-8.8.yaml"]'), matrix.stack-yaml) }}
+      run: |
+        export "NIX_PATH=nixpkgs=$(nix run .#print-nixpkgs-master)"
+        stack test --nix --stack-yaml ${{matrix.stack-yaml}}
+
+    - name: Run integration test
+      # The test is flaky on GHC 8.0 so we don't run it. As long as the tests
+      # above pass, it's unlikely that we'll introduce a bug that we will
+      # only catch through the integration test on this version and not other
+      # versions.
+      if: ${{ !contains(fromJSON('["stack/stack-8.0.yaml", "stack/stack-8.2.yaml"]'), matrix.stack-yaml) }}
+      run: |
+        set -e
+
+        export "NIX_PATH=nixpkgs=$(nix run .#print-nixpkgs-master)"
+
+        nix build .#jupyterlab
+        export PATH="$(pwd)/result/bin:$(pwd)/.local/bin:$PATH"
+
+        stack install --nix --stack-yaml ${{matrix.stack-yaml}}
+
+        echo "PATH: $PATH"
+        echo "jupyter: $(which jupyter)"
+        echo "ihaskell: $(which ihaskell)"
+
+        ihaskell install --stack
+
+        jupyter-kernelspec list
+
+        # Ensure that IHaskell notebook remains unchanged.
+        # Run the notebook to regenerate the outputs, then compare the new notebook to the old one.
+        test/acceptance.nbconvert.sh stack exec --nix --no-nix-pure --stack-yaml ${{matrix.stack-yaml}} -- jupyter nbconvert
diff --git a/Dockerfile b/Dockerfile
index e48232dd..bdf8ded4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
 # should match the GHC version of the stack.yaml resolver
 # checked in CI
-ARG GHC_VERSION=9.4.5
+ARG GHC_VERSION=9.4.7
 
 FROM haskell:${GHC_VERSION} AS ihaskell_base
 
diff --git a/flake.lock b/flake.lock
index b60ec0c7..4aed20f6 100644
--- a/flake.lock
+++ b/flake.lock
@@ -3,27 +3,11 @@
     "flake-compat": {
       "flake": false,
       "locked": {
-        "lastModified": 1627913399,
-        "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=",
+        "lastModified": 1673956053,
+        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
         "owner": "edolstra",
         "repo": "flake-compat",
-        "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-compat_2": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1627913399,
-        "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2",
+        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
         "type": "github"
       },
       "original": {
@@ -48,12 +32,15 @@
       }
     },
     "flake-utils_2": {
+      "inputs": {
+        "systems": "systems"
+      },
       "locked": {
-        "lastModified": 1629481132,
-        "narHash": "sha256-JHgasjPR0/J1J3DRm4KxM4zTyAj4IOJY8vIl75v/kPI=",
+        "lastModified": 1685518550,
+        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "997f7efcb746a9c140ce1f13c72263189225f482",
+        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
         "type": "github"
       },
       "original": {
@@ -62,36 +49,18 @@
         "type": "github"
       }
     },
-    "gitignore": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1611672876,
-        "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=",
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "rev": "211907489e9f198594c0eb0ca9256a1949c9d412",
-        "type": "github"
-      },
-      "original": {
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "type": "github"
-      }
-    },
     "hls": {
       "inputs": {
-        "flake-compat": "flake-compat_2",
+        "flake-compat": "flake-compat",
         "flake-utils": "flake-utils_2",
-        "gitignore": "gitignore",
-        "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
+        "nixpkgs": "nixpkgs"
       },
       "locked": {
-        "lastModified": 1637213318,
-        "narHash": "sha256-ZgxPwV7t4DyGYP7aXoetq+JHtd73XlOV2fYSflQmOXw=",
+        "lastModified": 1700698084,
+        "narHash": "sha256-5HcHQ/GLcPrJk7Dn7xQGb+O5ZwJE/QNj+plWyHNuP38=",
         "owner": "haskell",
         "repo": "haskell-language-server",
-        "rev": "311107eabbf0537e0c192b2c377d282505b4eff1",
+        "rev": "7db6215c6da39b6550d7c1ce6ea5b1bbe6e6dfde",
         "type": "github"
       },
       "original": {
@@ -100,69 +69,91 @@
         "type": "github"
       }
     },
+    "nix-filter": {
+      "locked": {
+        "lastModified": 1694857738,
+        "narHash": "sha256-bxxNyLHjhu0N8T3REINXQ2ZkJco0ABFPn6PIe2QUfqo=",
+        "owner": "numtide",
+        "repo": "nix-filter",
+        "rev": "41fd48e00c22b4ced525af521ead8792402de0ea",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "nix-filter",
+        "type": "github"
+      }
+    },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1630887066,
-        "narHash": "sha256-0ecIlrLsNIIa+zrNmzXXmbMBLZlmHU/aWFsa4bq99Hk=",
+        "lastModified": 1694477507,
+        "narHash": "sha256-RtUmM5s6vnx1W+tnrGzXArVScJ/IoGmqCLM177k5O5A=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "5e47a07e9f2d7ed999f2c7943b0896f5f7321ca3",
+        "rev": "ff303118b2ec262eb342eab88ae79318fac66d52",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
+        "ref": "haskell-updates",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
-    "nixpkgs_2": {
+    "nixpkgs23_05": {
       "locked": {
-        "lastModified": 1634515797,
-        "narHash": "sha256-elgCUC2khtBkOSpE4gDymNvthTZAI4hGI2iNu3YEUkA=",
+        "lastModified": 1701053011,
+        "narHash": "sha256-8QQ7rFbKFqgKgLoaXVJRh7Ik5LtI3pyBBCfOnNOGkF0=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "5f0194220f2402b06f7f79bba6351895facb5acb",
+        "rev": "5b528f99f73c4fad127118a8c1126b5e003b01a9",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-unstable",
+        "ref": "release-23.05",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-utils": [
-          "hls",
-          "flake-utils"
-        ],
-        "nixpkgs": [
-          "hls",
-          "nixpkgs"
-        ]
-      },
+    "nixpkgsMaster": {
       "locked": {
-        "lastModified": 1624971177,
-        "narHash": "sha256-Amf/nBj1E77RmbSSmV+hg6YOpR+rddCbbVgo5C7BS0I=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "397f0713d007250a2c7a745e555fa16c5dc8cadb",
+        "lastModified": 1700608285,
+        "narHash": "sha256-JAzapARzm6IfwDzBXNgNfFfAG3Fsr15pKLh/bZc7pU4=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "86eb3a994ed6f101ed4b3c19025e8133423bcca8",
         "type": "github"
       },
       "original": {
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
+        "owner": "NixOS",
+        "ref": "master",
+        "repo": "nixpkgs",
         "type": "github"
       }
     },
     "root": {
       "inputs": {
-        "flake-compat": "flake-compat",
         "flake-utils": "flake-utils",
         "hls": "hls",
-        "nixpkgs": "nixpkgs_2"
+        "nix-filter": "nix-filter",
+        "nixpkgs23_05": "nixpkgs23_05",
+        "nixpkgsMaster": "nixpkgsMaster"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
       }
     }
   },
diff --git a/flake.nix b/flake.nix
index 378fd5b8..3eb1d3d5 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,118 +1,104 @@
 {
   description = "A Haskell kernel for IPython.";
 
-  inputs = {
+  inputs.nixpkgs23_05.url = "github:NixOS/nixpkgs/release-23.05";
+  inputs.nixpkgsMaster.url = "github:NixOS/nixpkgs/master";
+  inputs.flake-utils.url = "github:numtide/flake-utils";
+  inputs.hls.url = "github:haskell/haskell-language-server";
+  inputs.nix-filter.url = "github:numtide/nix-filter";
 
-    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
-    flake-utils.url = "github:numtide/flake-utils";
-    hls.url = "github:haskell/haskell-language-server";
+  outputs = { self, nixpkgs23_05, nixpkgsMaster, flake-utils, hls, nix-filter, ... }:
+    # "x86_64-darwin" "aarch64-darwin"
+    flake-utils.lib.eachSystem ["x86_64-linux"] (system: let
+      baseOverlay = self: super: { inherit nix-filter; };
+      pkgs23_05 = import nixpkgs23_05 { inherit system; overlays = [baseOverlay]; };
+      pkgsMaster = import nixpkgsMaster { inherit system; overlays = [baseOverlay]; };
 
-    flake-compat = {
-      url = "github:edolstra/flake-compat";
-      flake = false;
-    };
-  };
+      jupyterlab = pkgsMaster.python3.withPackages (ps: [ ps.jupyterlab ps.notebook ]);
 
-  outputs = { self, hls, nixpkgs, flake-utils, ... }:
-    flake-utils.lib.eachSystem ["x86_64-linux" "x86_64-darwin" "aarch64-darwin"] (system: let
+      versions = let
+        mkVersion = pkgsSrc: compiler: overlays: extraArgs: {
+          name = compiler;
+          value = (import pkgsSrc { inherit system; overlays = [baseOverlay] ++ overlays; }).callPackage ./nix/release.nix ({
+            inherit compiler;
+          } // extraArgs);
+        };
+        in
+          pkgsMaster.lib.listToAttrs [
+            (mkVersion nixpkgs23_05  "ghc810" [(import ./nix/overlay-8.10.nix)] {})
+            (mkVersion nixpkgs23_05  "ghc90"  [(import ./nix/overlay-9.0.nix)]  {})
+            (mkVersion nixpkgs23_05  "ghc92"  []                                {})
+            (mkVersion nixpkgsMaster "ghc94"  [(import ./nix/overlay-9.4.nix)]  {})
+            (mkVersion nixpkgsMaster "ghc96"  [(import ./nix/overlay-9.6.nix)]  {})
+            (mkVersion nixpkgsMaster "ghc98"  [(import ./nix/overlay-9.8.nix)]  { enableHlint = false; })
+          ];
 
-      pkgs = import nixpkgs {
-        inherit system;
-      };
-
-      compilerVersionFromHsPkgs = hsPkgs:
-        pkgs.lib.replaceStrings [ "." ] [ "" ] hsPkgs.ghc.version;
-
-      mkEnv = hsPkgs: displayPkgs:
-        import ./release.nix {
-          compiler = "ghc${compilerVersionFromHsPkgs hsPkgs}";
-          nixpkgs = pkgs;
-          packages = displayPkgs;
+      envs' = prefix: packages: pkgsMaster.lib.mapAttrs' (version: releaseFn: {
+        name = prefix + version;
+        value = (releaseFn {
+          # Note: this can be changed to other Jupyter systems like jupyter-console
+          extraEnvironmentBinaries = [ jupyterlab ];
           systemPackages = p: with p; [
             gnuplot # for the ihaskell-gnuplot runtime
           ];
+          inherit packages;
+        });
+      }) versions;
+
+      # Basic envs with Jupyterlab and IHaskell
+      envs = envs' "ihaskell-env-" (_: []);
+
+      # Envs with Jupyterlab, IHaskell, and all display packages
+      displayEnvs = envs' "ihaskell-env-display-" (p: with p; map (n: builtins.getAttr n p) (import ./nix/displays.nix));
+
+      exes = pkgsMaster.lib.mapAttrs' (envName: env: {
+        name = builtins.replaceStrings ["-env"] [""] envName;
+        value = env.ihaskellExe;
+      }) envs;
+
+      devShells = pkgsMaster.lib.mapAttrs' (version: releaseFn: {
+        name = "ihaskell-dev-" + version;
+        value = pkgsMaster.callPackage ./nix/mkDevShell.nix {
+          inherit hls system version;
+          haskellPackages = (releaseFn {}).haskellPackages;
+          ihaskellOverlay = (releaseFn {}).ihaskellOverlay;
         };
-
-      mkExe = hsPkgs: (mkEnv hsPkgs (_:[])).ihaskellExe;
-
-      ghcDefault = ghc8107;
-      ghc884  = pkgs.haskell.packages.ghc884;
-      ghc8107  = pkgs.haskell.packages.ghc8107;
-      ghc921  = pkgs.haskell.packages.ghc921;
-
-      pythonDevEnv = pkgs.python3.withPackages (p: [p.jupyterlab]);
-
-      mkDevShell = hsPkgs:
-        let
-          myIHaskell = (mkPackage hsPkgs);
-          compilerVersion = compilerVersionFromHsPkgs hsPkgs;
-
-          myModifier = drv:
-            pkgs.haskell.lib.addBuildTools drv (with hsPkgs; [
-              cabal-install
-              pythonDevEnv
-              self.inputs.hls.packages.${system}."haskell-language-server-${compilerVersion}"
-              pkgs.cairo # for the ihaskell-charts HLS dev environment
-              pkgs.pango # for the ihaskell-diagrams HLS dev environment
-              pkgs.lapack # for the ihaskell-plot HLS dev environment
-              pkgs.blas # for the ihaskell-plot HLS dev environment
-            ]);
-        in (myModifier myIHaskell).envFunc {withHoogle=true;};
-
-
-      mkPackage = hsPkgs:
-        let
-          compilerVersion = pkgs.lib.replaceStrings [ "." ] [ "" ] hsPkgs.ghc.version;
-        in
-        hsPkgs.developPackage {
-          root =  pkgs.lib.cleanSource ./.;
-          name = "ihaskell";
-          returnShellEnv = false;
-          modifier = pkgs.haskell.lib.dontCheck;
-          overrides = (mkEnv hsPkgs (_:[])).ihaskellOverlay ;
-          withHoogle = true;
-        };
+      }) versions;
 
     in {
+      packages = envs // displayEnvs // exes // devShells // rec  {
+        # For easily testing that everything builds
+        allEnvs = pkgsMaster.linkFarm "ihaskell-envs" envs;
+        allDisplayEnvs = pkgsMaster.linkFarm "ihaskell-display-envs" displayEnvs;
+        allExes = pkgsMaster.linkFarm "ihaskell-exes" exes;
+        allDevShells = pkgsMaster.linkFarm "ihaskell-dev-shells" devShells;
 
-      packages = {
-        # Development environment
-        ihaskell-dev = mkDevShell ghcDefault;
-        ihaskell-dev-921 = mkDevShell ghc921;
-        ihaskell-dev-8107 = mkDevShell ghc8107;
-        ihaskell-dev-884 = mkDevShell ghc884;
-
-        # IHaskell kernel
-        ihaskell = mkExe ghcDefault;
-        ihaskell-8107 = mkExe ghc8107;
-        ihaskell-921 = mkExe ghc921;
-
-        # Full Jupyter environment
-        # I actually wish those would disappear ? let jupyterWith or use deal with it
-        ihaskell-env = mkEnv ghcDefault (_:[]);
-        ihaskell-env-8107 = mkEnv ghc8107 (_:[]);
-
-        # Full Jupyter environment with all Display modules (build is not incremental)
-        #
-        #     result/bin/jupyter-lab
-        #
-        ihaskell-env-display = mkEnv ghcDefault (p: with p; [
-            ihaskell-aeson
-            ihaskell-blaze
-            ihaskell-charts
-            ihaskell-diagrams
-            ihaskell-gnuplot
-            ihaskell-graphviz
-            ihaskell-hatex
-            ihaskell-juicypixels
-            ihaskell-magic
-            ihaskell-plot
-            ihaskell-widgets
-            ]);
+        # For getting Nix paths in CI
+        print-nixpkgs-stable = pkgsMaster.writeShellScriptBin "print-nixpkgs-stable.sh" "echo ${pkgs23_05.path}";
+        print-nixpkgs-master = pkgsMaster.writeShellScriptBin "print-nixpkgs-master.sh" "echo ${pkgsMaster.path}";
+        inherit jupyterlab;
       };
 
-      defaultPackage = self.packages.${system}.ihaskell;
+      # Run the acceptance tests on each env
+      checks = pkgsMaster.lib.mapAttrs (envName: env:
+        pkgsMaster.stdenv.mkDerivation {
+          name = envName + "-check";
+          src = pkgsMaster.callPackage ./nix/ihaskell-src.nix {};
+          nativeBuildInputs = with pkgsMaster; [jq bash];
+          doCheck = true;
+          checkPhase = ''
+            mkdir -p home
+            export HOME=$(pwd)/home
+            bash ./test/acceptance.nbconvert.sh ${env}/bin/jupyter nbconvert
+          '';
+          installPhase = ''
+            touch $out
+          '';
+        }
+      ) envs;
 
-      devShell = self.packages.${system}.ihaskell-dev;
+      defaultPackage = self.packages.${system}.ihaskell-ghc810;
+
+      devShell = self.packages.${system}.ihaskell-dev-ghc810;
     });
 }
diff --git a/ihaskell-display/ihaskell-widgets/src/IHaskell/Display/Widgets/Singletons.hs b/ihaskell-display/ihaskell-widgets/src/IHaskell/Display/Widgets/Singletons.hs
index f81e46ac..416c33da 100644
--- a/ihaskell-display/ihaskell-widgets/src/IHaskell/Display/Widgets/Singletons.hs
+++ b/ihaskell-display/ihaskell-widgets/src/IHaskell/Display/Widgets/Singletons.hs
@@ -299,4 +299,4 @@ promote
 
     -- hasKey :: Field -> Bool
     hasKey x = toKey x /= ""
-  |]
\ No newline at end of file
+  |]
diff --git a/ihaskell-display/ihaskell-widgets/src/IHaskell/Display/Widgets/Types.hs b/ihaskell-display/ihaskell-widgets/src/IHaskell/Display/Widgets/Types.hs
index 74777f9f..51d8b5c8 100644
--- a/ihaskell-display/ihaskell-widgets/src/IHaskell/Display/Widgets/Types.hs
+++ b/ihaskell-display/ihaskell-widgets/src/IHaskell/Display/Widgets/Types.hs
@@ -64,13 +64,13 @@
 -- specification.
 module IHaskell.Display.Widgets.Types where
 
-import           Control.Monad (unless, join, when, void,mzero)
 import           Control.Applicative ((<$>))
 import qualified Control.Exception as Ex
-import           Data.Typeable (Typeable, TypeRep, typeOf)
+import           Control.Monad (unless, join, when, void,mzero)
 import           Data.IORef (IORef, readIORef, modifyIORef)
 import           Data.String
 import           Data.Text (Text, pack)
+import           Data.Typeable (Typeable, TypeRep, typeOf)
 import           System.IO.Error
 import           System.Posix.IO
 import           Text.Printf (printf)
@@ -904,7 +904,11 @@ noStdin action =
       handler e = when (ioeGetErrorType e == InvalidArgument)
                     (error "Widgets cannot do console input, sorry :)")
   in Ex.handle handler $ do
+#if MIN_VERSION_unix(2,8,0)
+    nullFd <- openFd "/dev/null" WriteOnly defaultFileFlags
+#else
     nullFd <- openFd "/dev/null" WriteOnly Nothing defaultFileFlags
+#endif
     oldStdin <- dup stdInput
     void $ dupTo nullFd stdInput
     closeFd nullFd
diff --git a/nix/displays.nix b/nix/displays.nix
new file mode 100644
index 00000000..4d99bf8d
--- /dev/null
+++ b/nix/displays.nix
@@ -0,0 +1,15 @@
+[
+  "ihaskell-aeson"
+  "ihaskell-blaze"
+  "ihaskell-charts"
+  "ihaskell-diagrams"
+  "ihaskell-gnuplot"
+  "ihaskell-graphviz"
+  "ihaskell-hatex"
+  "ihaskell-juicypixels"
+  "ihaskell-magic"
+  "ihaskell-plot"
+  # "ihaskell-rlangqq"
+  # "ihaskell-static-canvas"
+  "ihaskell-widgets"
+]
diff --git a/nix/ihaskell-overlay.nix b/nix/ihaskell-overlay.nix
new file mode 100644
index 00000000..17d34f1f
--- /dev/null
+++ b/nix/ihaskell-overlay.nix
@@ -0,0 +1,41 @@
+{ callPackage
+, haskell
+, lib
+
+, compiler
+, enableHlint
+}:
+
+self: super:
+
+let
+  ihaskell-src = callPackage ./ihaskell-src.nix {};
+
+  displays = let
+    mkDisplay = display: {
+      name = display;
+      value = self.callCabal2nix display "${ihaskell-src}/ihaskell-display/${display}" {};
+    };
+  in
+    builtins.listToAttrs (map mkDisplay (import ./displays.nix));
+
+in
+
+{
+  ihaskell = let
+    baseIhaskell = haskell.lib.overrideCabal (self.callCabal2nix "ihaskell" ihaskell-src {}) (_drv: {
+      preCheck = ''
+        export HOME=$TMPDIR/home
+        export PATH=$PWD/dist/build/ihaskell:$PATH
+        export GHC_PACKAGE_PATH=$PWD/dist/package.conf.inplace/:$GHC_PACKAGE_PATH
+      '';
+      configureFlags = (_drv.configureFlags or []) ++ (lib.optionals (!enableHlint) [ "-f" "-use-hlint" ]);
+    });
+  in
+    if enableHlint
+    then baseIhaskell
+    else baseIhaskell.overrideScope (self: super: { hlint = null; });
+
+  ghc-parser     = self.callCabal2nix "ghc-parser" (builtins.path { path = ../ghc-parser; name = "ghc-parser-src"; }) {};
+  ipython-kernel = self.callCabal2nix "ipython-kernel" (builtins.path { path = ../ipython-kernel; name = "ipython-kernel-src"; }) {};
+} // displays
diff --git a/nix/ihaskell-src.nix b/nix/ihaskell-src.nix
new file mode 100644
index 00000000..8bf1d5b2
--- /dev/null
+++ b/nix/ihaskell-src.nix
@@ -0,0 +1,19 @@
+{ nix-filter
+}:
+
+nix-filter {
+  root = ../.;
+  include = [
+    "LICENSE"
+    "Setup.hs"
+    "ghc-parser"
+    "html"
+    "ihaskell-display"
+    "ihaskell.cabal"
+    "ipython-kernel"
+    "jupyterlab-ihaskell"
+    "main"
+    "src"
+    "test"
+  ];
+}
diff --git a/nix/mkDevShell.nix b/nix/mkDevShell.nix
new file mode 100644
index 00000000..9f252fbb
--- /dev/null
+++ b/nix/mkDevShell.nix
@@ -0,0 +1,40 @@
+{ pkgs
+
+, hls
+, system
+, version
+, haskellPackages
+, ihaskellOverlay
+}:
+
+let
+  compilerVersion = builtins.substring 3 100 version;
+
+  devIHaskell = haskellPackages.developPackage {
+    root =  pkgs.lib.cleanSource ../.;
+    name = "ihaskell";
+    returnShellEnv = false;
+    modifier = pkgs.haskell.lib.dontCheck;
+    overrides = ihaskellOverlay;
+    withHoogle = true;
+  };
+
+  devModifier = drv:
+    pkgs.haskell.lib.addBuildTools drv (with haskellPackages; [
+      cabal-install
+      (pkgs.python3.withPackages (p: [p.jupyterlab]))
+
+      # Note: HLS support currently doesn't work, because the HLS project has removed
+      # HLS binaries from their flake; see
+      # https://github.com/haskell/haskell-language-server/pull/3804
+      # hls.packages.${system}."haskell-language-server-${compilerVersion}"
+
+      pkgs.cairo # for the ihaskell-charts HLS dev environment
+      pkgs.pango # for the ihaskell-diagrams HLS dev environment
+      pkgs.lapack # for the ihaskell-plot HLS dev environment
+      pkgs.blas # for the ihaskell-plot HLS dev environment
+    ]);
+
+in
+
+(devModifier devIHaskell).envFunc {withHoogle=true;}
diff --git a/nix/overlay-8.10.nix b/nix/overlay-8.10.nix
new file mode 100644
index 00000000..0527f964
--- /dev/null
+++ b/nix/overlay-8.10.nix
@@ -0,0 +1,16 @@
+sel: sup: {
+  haskell = sup.haskell // {
+    packages = sup.haskell.packages // {
+      ghc810 = sup.haskell.packages.ghc810.override {
+        overrides = self: super: {
+          # Note that singletons-3.x broke the library into separate pieces like
+          # singletons-th. singletons-3.x will build with GHC 8.10, but we don't have
+          # the conditional compilation in the cabal file to handle this. The CPP
+          # in IHaskell.Display.Widgets.Singletons needs updating too.
+          singletons = self.callHackage "singletons" "2.7" {};
+          th-desugar = self.callHackage "th-desugar" "1.11" {};
+        };
+      };
+    };
+  };
+}
diff --git a/nix/overlay-9.0.nix b/nix/overlay-9.0.nix
new file mode 100644
index 00000000..01fe5293
--- /dev/null
+++ b/nix/overlay-9.0.nix
@@ -0,0 +1,13 @@
+sel: sup: {
+  haskell = sup.haskell // {
+    packages = sup.haskell.packages // {
+      ghc90 = sup.haskell.packages.ghc90.override {
+        overrides = self: super: {
+          singletons-base = self.callHackage "singletons-base" "3.0" {};
+          singletons-th = self.callHackage "singletons-th" "3.0" {};
+          th-desugar = self.callHackage "th-desugar" "1.12" {};
+        };
+      };
+    };
+  };
+}
diff --git a/nix/overlay-9.4.nix b/nix/overlay-9.4.nix
new file mode 100644
index 00000000..1be9c3d9
--- /dev/null
+++ b/nix/overlay-9.4.nix
@@ -0,0 +1,20 @@
+sel: sup: {
+  haskell = sup.haskell // {
+    packages = sup.haskell.packages // {
+      ghc94 = sup.haskell.packages.ghc94.override {
+        overrides = self: super: {
+          ghc-syntax-highlighter = super.callCabal2nix "ghc-syntax-highlighter" (sup.fetchFromGitHub {
+            owner = "mrkkrp";
+            repo = "ghc-syntax-highlighter";
+            # 0.0.10.0
+            rev = "71ff751eaa6034d4aef254d6bc5a8be4f6595344";
+            sha256 = "wQmWSuvIJpg11zKl1qOSWpqxjp2DoJwa20vaS2KHypM=";
+          }) {};
+
+          ghc-lib-parser = super.ghc-lib-parser_9_6_3_20231014;
+          ghc-lib-parser-ex = super.ghc-lib-parser-ex_9_6_0_2;
+        };
+      };
+    };
+  };
+}
diff --git a/nix/overlay-9.6.nix b/nix/overlay-9.6.nix
new file mode 100644
index 00000000..21c1d5c3
--- /dev/null
+++ b/nix/overlay-9.6.nix
@@ -0,0 +1,35 @@
+sel: sup: {
+  haskell = sup.haskell // {
+    packages = sup.haskell.packages // {
+      ghc96 = sup.haskell.packages.ghc96.override {
+        overrides = self: super: {
+          ghc-syntax-highlighter = super.callCabal2nix "ghc-syntax-highlighter" (sup.fetchFromGitHub {
+            owner = "mrkkrp";
+            repo = "ghc-syntax-highlighter";
+            # 0.0.10.0
+            rev = "71ff751eaa6034d4aef254d6bc5a8be4f6595344";
+            sha256 = "wQmWSuvIJpg11zKl1qOSWpqxjp2DoJwa20vaS2KHypM=";
+          }) {};
+
+          ghc-lib-parser = self.ghc-lib-parser_9_6_3_20231014;
+
+          zeromq4-haskell = super.zeromq4-haskell.overrideAttrs (oldAttrs: {
+            buildInputs = oldAttrs.buildInputs ++ [super.libsodium];
+          });
+
+          # https://github.com/amcphail/plot/pull/23
+          plot = super.callCabal2nix "plot" (sup.fetchFromGitHub {
+            owner = "codedownio";
+            repo = "haskell-plot";
+            rev = "dfa26022b5815bcd6a5dd6c818fcd2c4d25c6d44";
+            sha256 = "1snk70l7q98cqflgaqf6l75g4hpcnf284flm9rsmk8kkzd5nnh5k";
+          }) {};
+
+          singletons-base = sup.haskell.lib.dontCheck (self.callHackage "singletons-base" "3.2" {});
+          singletons-th = self.callHackage "singletons-th" "3.2" {};
+          th-desugar = self.callHackage "th-desugar" "1.15" {};
+        };
+      };
+    };
+  };
+}
diff --git a/nix/overlay-9.8.nix b/nix/overlay-9.8.nix
new file mode 100644
index 00000000..410bea2f
--- /dev/null
+++ b/nix/overlay-9.8.nix
@@ -0,0 +1,64 @@
+sel: sup: {
+  haskell = sup.haskell // {
+    packages = sup.haskell.packages // {
+      ghc98 = sup.haskell.packages.ghc98.override {
+        overrides = self: super: {
+          aeson = self.callHackage "aeson" "2.2.1.0" {};
+          alex = sup.haskell.lib.dontCheck super.alex;
+          bifunctors = self.callHackage "bifunctors" "5.6.1" {};
+          doctest = self.callHackage "doctest" "0.22.2" {};
+          ghc-lib-parser = sup.haskell.lib.overrideCabal (self.callHackage "ghc-lib-parser" "9.8.1.20231009" {}) (_drv: {
+            postPatch = let
+              original-a = "cabal-version: 2.0";
+              replacement-a = "cabal-version: 3.0";
+              original-b = "license: BSD3";
+              replacement-b = "license: BSD-3-Clause";
+              original-c =
+                "c-sources:\r\n        libraries/ghc-heap/cbits/HeapPrim.cmm";
+              replacement-c =
+                "cmm-sources:\r\n        libraries/ghc-heap/cbits/HeapPrim.cmm";
+            in ''
+                substituteInPlace ./ghc-lib-parser.cabal --replace \
+                  '${original-a}' '${replacement-a}'
+                substituteInPlace ./ghc-lib-parser.cabal --replace \
+                  '${original-b}' '${replacement-b}'
+                substituteInPlace ./ghc-lib-parser.cabal --replace \
+                  '${original-c}' '${replacement-c}'
+              '';
+          });
+          ghc-lib-parser-ex = super.ghc-lib-parser-ex_9_8_0_0;
+          ghc-syntax-highlighter = self.callCabal2nix "ghc-syntax-highlighter" (sup.fetchFromGitHub {
+            owner = "mrkkrp";
+            repo = "ghc-syntax-highlighter";
+            rev = "336df42e9185c2e2a91fa71eaa18b51f0f5437de";
+            sha256 = "0nnpyq3z6c90z3j8xzw2gcj13nhihc7xa0sb4xbbdpxfnidplp9q";
+          }) {};
+          haskell-src-meta = sup.haskell.lib.appendPatch (sup.haskell.lib.doJailbreak super.haskell-src-meta) (sup.fetchpatch {
+            url = "https://gitlab.haskell.org/ghc/head.hackage/-/raw/master/patches/haskell-src-meta-0.8.12.patch";
+            sha256 = "0wn0lnq522bhc65sw02jm448mg5ijdxwgs7gzp9xp6z8ir1a0bzr";
+          });
+          here = sup.haskell.lib.doJailbreak (self.callHackage "here" "1.2.14" {});
+          hourglass = sup.haskell.lib.dontCheck super.hourglass;
+          hspec = self.callHackage "hspec" "2.11.6" {};
+          hspec-core = sup.haskell.lib.dontCheck (self.callHackage "hspec-core" "2.11.6" {});
+          hspec-discover = self.callHackage "hspec-discover" "2.11.6" {};
+          hspec-expectations = self.callHackage "hspec-expectations" "0.8.4" {};
+          hspec-meta = self.callHackage "hspec-meta" "2.11.6" {};
+          lifted-base = sup.haskell.lib.dontCheck super.lifted-base;
+          semigroupoids = self.callHackage "semigroupoids" "6.0.0.1" {};
+          shelly = sup.haskell.lib.doJailbreak super.shelly;
+          tagged = self.callHackage "tagged" "0.8.8" {};
+          th-abstraction = self.callHackage "th-abstraction" "0.6.0.0" {};
+          th-lift = self.callHackage "th-lift" "0.8.4" {};
+          unliftio-core = sup.haskell.lib.doJailbreak super.unliftio-core;
+
+          # For display libs (in progress)
+          statestack = sup.haskell.lib.doJailbreak super.statestack;
+          # TODO: wait for nixpkgs master to update Hackage pin to have this diagrams-core version
+          diagrams-core = self.callHackage "diagrams-core" "1.5.1.1" {};
+          diagrams-lib = sup.haskell.lib.doJailbreak super.diagrams-lib;
+        };
+      };
+    };
+  };
+}
diff --git a/nix/release.nix b/nix/release.nix
new file mode 100644
index 00000000..ef2bc159
--- /dev/null
+++ b/nix/release.nix
@@ -0,0 +1,109 @@
+{ lib
+, buildEnv
+, callPackage
+, haskell
+, makeWrapper
+, pkgs
+, runCommand
+, writeShellScriptBin
+
+# Compiler name as a string, like "ghc92".
+# Must be a kernel found within pkgs.haskell.packages.*.
+, compiler
+# Whether to enable hlint.
+, enableHlint ? true
+}:
+
+{
+# Extra binaries to include in the final environment, like jupyter-lab or jupyter-console.
+# Will have their JUPYTER_PATH and PATH environment variables prefixed to tell them about the kernel.
+extraEnvironmentBinaries ? []
+# Haskell packages to include. First argument is an attrset of available packages.
+, packages ? (_: [])
+# RTS options passed when invoking IHaskell in the kernelspec.
+, rtsopts ? "-M3g -N2"
+, staticExecutable ? false
+, systemPackages ? (_: [])
+}:
+
+let
+  ihaskellOverlay = callPackage ./ihaskell-overlay.nix { inherit compiler enableHlint; };
+
+  # Haskell packages set with IHaskell packages added
+  haskellPackages = haskell.packages."${compiler}".override (old: {
+    overrides = lib.composeExtensions
+      (old.overrides or (_: _: {}))
+      ihaskellOverlay;
+  });
+
+  # GHC with desired packages. This includes user-configured packages plus IHaskell itself, so
+  # you can import things like IHaskell.Display
+  ihaskellEnv = haskellPackages.ghcWithPackages (ps: (packages ps) ++ [ps.ihaskell]);
+
+  # ihaskell binary wrapper which adds the "-l" argument
+  ihaskellGhcLib = writeShellScriptBin "ihaskell" ''
+    ${ihaskellEnv}/bin/ihaskell -l $(${ihaskellEnv}/bin/ghc --print-libdir) "$@"
+  '';
+
+  # Jupyter directory with kernels/haskell/kernel.json, plus logo and kernel.js
+  jupyterDirKernel = let
+    kernelFile = {
+      display_name = "Haskell";
+      argv = [
+        "${ihaskellGhcLib}/bin/ihaskell"
+        "kernel"
+        "{connection_file}"
+        "+RTS"
+      ] ++ (lib.splitString " " rtsopts) ++ [
+        "-RTS"
+      ];
+      language = "haskell";
+    };
+  in
+    runCommand "ihaskell-kernel" {} ''
+      export kerneldir=$out/kernels/haskell
+      mkdir -p $kerneldir
+      cp ${../html}/* $kerneldir
+      echo '${builtins.toJSON kernelFile}' > $kerneldir/kernel.json
+    '';
+
+  # Separate Jupyter directory with the "labextensions" dir.
+  # TODO: just copy this alongside the HTML in jupyterDir?
+  jupyterDirLabExtensions = runCommand "ihaskell-labextension" {} ''
+    mkdir -p $out/labextensions/
+    ln -s ${../jupyterlab-ihaskell/labextension} $out/labextensions/jupyterlab-ihaskell
+  '';
+
+  # Combine the paths in jupyterDirKernel and jupyterDirLabExtensions
+  ihaskellDataDir = buildEnv {
+    name = "ihaskell-data-dir-" + compiler;
+    paths = [ jupyterDirKernel jupyterDirLabExtensions ];
+  };
+
+in
+
+# Final IHaskell environment:
+buildEnv {
+  name = "ihaskell-with-packages-" + compiler;
+  nativeBuildInputs = [ makeWrapper ];
+  paths = [ ihaskellEnv ] ++ extraEnvironmentBinaries;
+  postBuild = ''
+    for prg in $out/bin"/"*;do
+      if [[ -f $prg && -x $prg ]]; then
+        wrapProgram $prg \
+          --prefix PATH : "${lib.makeBinPath ([ihaskellEnv] ++ (systemPackages pkgs))}" \
+          --prefix JUPYTER_PATH : "${ihaskellDataDir}"
+      fi
+    done
+  '';
+
+  passthru = {
+    inherit haskellPackages;
+    inherit ihaskellOverlay;
+    # statically linking against haskell libs reduces closure size at the expense
+    # of startup/reload time, so we make it configurable
+    ihaskellExe = if staticExecutable
+                  then haskell.lib.justStaticExecutables haskellPackages.ihaskell
+                  else haskell.lib.enableSharedExecutables haskellPackages.ihaskell;
+  };
+}
diff --git a/release-9.2.nix b/release-9.2.nix
deleted file mode 100644
index 6c9d6358..00000000
--- a/release-9.2.nix
+++ /dev/null
@@ -1,9 +0,0 @@
-{ compiler ? "ghc928"
-, nixpkgs ? import <nixpkgs> {}
-, packages ? (_: [])
-, pythonPackages ? (_: [])
-, rtsopts ? "-M3g -N2"
-, staticExecutable ? false
-, systemPackages ? (_: [])
-}:
-  import (./release.nix) { inherit compiler nixpkgs packages pythonPackages rtsopts systemPackages; }
diff --git a/release-9.4.nix b/release-9.4.nix
deleted file mode 100644
index 0e125f50..00000000
--- a/release-9.4.nix
+++ /dev/null
@@ -1,122 +0,0 @@
-let
-  nixpkgs-src = builtins.fetchTarball {
-    url = "https://github.com/NixOS/nixpkgs/tarball/e0990771a605839bc63eaef5edadffb48a040664";
-    sha256 = "sha256:06ja7660glz88ji311ds98frqgf5780c51m9l6chrmj0gh2zf7k9";
-  };
-in
-{ compiler ? "ghc942"
-, nixpkgs ? import nixpkgs-src {}
-, packages ? (_: [])
-, pythonPackages ? (_: [])
-, rtsopts ? "-M3g -N2"
-, staticExecutable ? false
-, systemPackages ? (_: [])
-}:
-let
-  ihaskell-src = nixpkgs.nix-gitignore.gitignoreSource
-    [ "**/*.ipynb" "**/*.nix" "**/*.yaml" "**/*.yml" "**/\.*" "/Dockerfile" "/README.md" "/cabal.project" "/images" "/notebooks" "/requirements.txt" ]
-    ./.;
-  displays = self: builtins.listToAttrs (
-    map
-      (display: { name = "ihaskell-${display}"; value = self.callCabal2nix display "${ihaskell-src}/ihaskell-display/ihaskell-${display}" {}; })
-      [ "aeson" "blaze" "charts" "diagrams" "gnuplot" "graphviz" "hatex" "juicypixels" "magic" "plot" "rlangqq" "static-canvas" "widgets" ]);
-  haskellPackages = nixpkgs.haskell.packages."${compiler}".override (old: {
-    overrides = nixpkgs.lib.composeExtensions (old.overrides or (_: _: {})) ihaskellOverlay;
-  });
-
-  ihaskellOverlay = (self: super: {
-    ihaskell = nixpkgs.haskell.lib.overrideCabal (
-                     self.callCabal2nix "ihaskell" ihaskell-src {}) (_drv: {
-      preCheck = ''
-        export HOME=$TMPDIR/home
-        export PATH=$PWD/dist/build/ihaskell:$PATH
-        export GHC_PACKAGE_PATH=$PWD/dist/package.conf.inplace/:$GHC_PACKAGE_PATH
-      '';
-    });
-    ghc-parser     = self.callCabal2nix "ghc-parser" (builtins.path { path = ./ghc-parser; name = "ghc-parser-src"; }) {};
-    ghc-syntax-highlighter = let
-      src = nixpkgs.fetchFromGitHub {
-        owner = "mrkkrp";
-        repo = "ghc-syntax-highlighter";
-        rev = "bbc049904524aae08e6431494f41fe2a288f6259";
-        sha256 = "sha256-w7AxGsUfqGhh7wrSPppQ2+gPwjvb4mwExJdDOcasAZ4=";
-      };
-      in
-        self.callCabal2nix "ghc-syntax-highlighter" src {};
-    ipython-kernel = self.callCabal2nix "ipython-kernel" (builtins.path { path = ./ipython-kernel; name = "ipython-kernel-src"; }) {};
-
-    hlint           = super.hlint_3_5;
-    zeromq4-haskell = nixpkgs.haskell.lib.addPkgconfigDepend super.zeromq4-haskell nixpkgs.libsodium;
-  } // displays self);
-
-  # statically linking against haskell libs reduces closure size at the expense
-  # of startup/reload time, so we make it configurable
-  ihaskellExe = if staticExecutable
-    then nixpkgs.haskell.lib.justStaticExecutables haskellPackages.ihaskell
-    else nixpkgs.haskell.lib.enableSharedExecutables haskellPackages.ihaskell;
-  ihaskellEnv = haskellPackages.ghcWithPackages packages;
-  jupyterlab = nixpkgs.python3.withPackages (ps: [ ps.jupyterlab ] ++ pythonPackages ps);
-  ihaskellGhcLibFunc = exe: env: nixpkgs.writeShellScriptBin "ihaskell" ''
-    ${exe}/bin/ihaskell -l $(${env}/bin/ghc --print-libdir) "$@"
-  '';
-  ihaskellKernelFileFunc = ihaskellGhcLib: rtsopts: {
-    display_name = "Haskell";
-    argv = [
-      "${ihaskellGhcLib}/bin/ihaskell"
-      "kernel"
-      "{connection_file}"
-      "+RTS"
-    ] ++ (nixpkgs.lib.splitString " " rtsopts) ++ [
-      "-RTS"
-    ];
-    language = "haskell";
-  };
-  ihaskellKernelSpecFunc = ihaskellKernelFile: nixpkgs.runCommand "ihaskell-kernel" {} ''
-    export kerneldir=$out/kernels/haskell
-    mkdir -p $kerneldir
-    cp ${./html}/* $kerneldir
-    echo '${builtins.toJSON ihaskellKernelFile}' > $kerneldir/kernel.json
-  '';
-  ihaskellLabextension = nixpkgs.runCommand "ihaskell-labextension" {} ''
-    mkdir -p $out/labextensions/
-    ln -s ${./jupyterlab-ihaskell/labextension} $out/labextensions/jupyterlab-ihaskell
-  '';
-  ihaskellDataDirFunc = ihaskellKernelSpec: ihaskellLabextension: nixpkgs.buildEnv {
-    name = "ihaskell-data-dir";
-    paths = [ ihaskellKernelSpec ihaskellLabextension ];
-  };
-  ihaskellBuildEnvFunc = { ihaskellEnv, jupyterlab, systemPackages, ihaskellDataDir }: nixpkgs.buildEnv {
-    name = "ihaskell-with-packages";
-    nativeBuildInputs = [ nixpkgs.makeWrapper ];
-    paths = [ ihaskellEnv jupyterlab ];
-    postBuild = ''
-      for prg in $out/bin"/"*;do
-        if [[ -f $prg && -x $prg ]]; then
-          wrapProgram $prg \
-            --prefix PATH : "${nixpkgs.lib.makeBinPath ([ihaskellEnv] ++ (systemPackages nixpkgs))}" \
-            --prefix JUPYTER_PATH : "${ihaskellDataDir}"
-        fi
-      done
-    '';
-    passthru = {
-      inherit haskellPackages;
-      inherit ihaskellExe;
-      inherit ihaskellEnv;
-      inherit ihaskellOverlay;
-      inherit ihaskellLabextension;
-      inherit jupyterlab;
-      inherit ihaskellGhcLibFunc;
-      inherit ihaskellKernelFileFunc;
-      inherit ihaskellKernelSpecFunc;
-      inherit ihaskellDataDirFunc;
-      inherit ihaskellBuildEnvFunc;
-    };
-  };
-in ihaskellBuildEnvFunc {
-  inherit ihaskellEnv jupyterlab systemPackages;
-  ihaskellDataDir = let
-    ihaskellGhcLib = ihaskellGhcLibFunc ihaskellExe ihaskellEnv;
-    ihaskellKernelFile = ihaskellKernelFileFunc ihaskellGhcLib rtsopts;
-    ihaskellKernelSpec = ihaskellKernelSpecFunc ihaskellKernelFile;
-  in ihaskellDataDirFunc ihaskellKernelSpec ihaskellLabextension;
-}
diff --git a/release-9.6.nix b/release-9.6.nix
deleted file mode 100644
index 261ef4f2..00000000
--- a/release-9.6.nix
+++ /dev/null
@@ -1,35 +0,0 @@
-let
-  nixpkgs-src = builtins.fetchTarball {
-    url = "https://github.com/NixOS/nixpkgs/tarball/02c6061679c99546ccff9ca241025134411e13ad";
-    sha256 = "sha256:03cwv27x1xl9fm2dzdgzm1lz9qimn3w10v8pb7wd4ld459jir8pb";
-  };
-  ghcVersion = "ghc963";
-  overlay = sel: sup: {
-    haskell = sup.haskell // {
-      packages = sup.haskell.packages // {
-        ${ghcVersion} = sup.haskell.packages.${ghcVersion}.override {
-          overrides = self: super: {
-            ghc-syntax-highlighter = let
-              src = sel.fetchFromGitHub {
-                owner = "mrkkrp";
-                repo = "ghc-syntax-highlighter";
-                rev = "71ff751eaa6034d4aef254d6bc5a8be4f6595344";
-                sha256 = "14yahxi4pnjbvcd9r843kn7b36jsjaixd99jswsrh9n8xd59c2f1";
-              };
-              in
-                self.callCabal2nix "ghc-syntax-highlighter" src {};
-          };
-        };
-      };
-    };
-  };
-in
-{ compiler ? ghcVersion
-, nixpkgs ? import nixpkgs-src { overlays = [ overlay ]; }
-, packages ? (_: [])
-, pythonPackages ? (_: [])
-, rtsopts ? "-M3g -N2"
-, staticExecutable ? false
-, systemPackages ? (_: [])
-}:
-  import (./release.nix) { inherit compiler nixpkgs packages pythonPackages rtsopts systemPackages; }
diff --git a/release-9.8.nix b/release-9.8.nix
deleted file mode 100644
index 4ea42df4..00000000
--- a/release-9.8.nix
+++ /dev/null
@@ -1,166 +0,0 @@
-let
-  nixpkgs-src = builtins.fetchTarball {
-    url = "https://github.com/NixOS/nixpkgs/tarball/0c086da2bb82029fd00e80bdc117a37a804fd7ff";
-    sha256 = "sha256:1c02n9i4y49cvyw8fylpsvbhiijdc0pppzgn3qwxw6nyj68i3590";
-  };
-in
-{ compiler ? "ghc981"
-, nixpkgs ? import nixpkgs-src {}
-, packages ? (_: [])
-, pythonPackages ? (_: [])
-, rtsopts ? "-M3g -N2"
-, staticExecutable ? false
-, systemPackages ? (_: [])
-}:
-let
-  ihaskell-src = nixpkgs.nix-gitignore.gitignoreSource
-    [ "**/*.ipynb" "**/*.nix" "**/*.yaml" "**/*.yml" "**/\.*" "/Dockerfile" "/README.md" "/cabal.project" "/images" "/notebooks" "/test" "/requirements.txt" ]
-    ./.;
-  displays = self: builtins.listToAttrs (
-    map
-      (display: { name = "ihaskell-${display}"; value = self.callCabal2nix display "${ihaskell-src}/ihaskell-display/ihaskell-${display}" {}; })
-      [ "aeson" "blaze" "charts" "diagrams" "gnuplot" "graphviz" "hatex" "juicypixels" "magic" "plot" "rlangqq" "static-canvas" "widgets" ]);
-  haskellPackages = nixpkgs.haskell.packages."${compiler}".override (old: {
-    overrides = nixpkgs.lib.composeExtensions (old.overrides or (_: _: {})) ihaskellOverlay;
-  });
-
-  ihaskellOverlay = (self: super: {
-    ihaskell = (nixpkgs.haskell.lib.overrideCabal (
-                     self.callCabal2nix "ihaskell" ihaskell-src {}) (_drv: {
-      preCheck = ''
-        export HOME=$TMPDIR/home
-        export PATH=$PWD/dist/build/ihaskell:$PATH
-        export GHC_PACKAGE_PATH=$PWD/dist/package.conf.inplace/:$GHC_PACKAGE_PATH
-      '';
-      configureFlags = (_drv.configureFlags or []) ++ [ "-f" "-use-hlint" ];
-    })).overrideScope (self: super: {
-      hlint = null;
-    });
-    ghc-parser     = self.callCabal2nix "ghc-parser" (builtins.path { path = ./ghc-parser; name = "ghc-parser-src"; }) {};
-    ghc-syntax-highlighter = let
-      src = nixpkgs.fetchFromGitHub {
-        owner = "mrkkrp";
-        repo = "ghc-syntax-highlighter";
-        rev = "336df42e9185c2e2a91fa71eaa18b51f0f5437de";
-        sha256 = "0nnpyq3z6c90z3j8xzw2gcj13nhihc7xa0sb4xbbdpxfnidplp9q";
-      };
-      in
-        self.callCabal2nix "ghc-syntax-highlighter" src {};
-    ipython-kernel = self.callCabal2nix "ipython-kernel" (builtins.path { path = ./ipython-kernel; name = "ipython-kernel-src"; }) {};
-
-    alex = nixpkgs.haskell.lib.dontCheck super.alex;
-    # zeromq4-haskell = nixpkgs.haskell.lib.addPkgconfigDepend super.zeromq4-haskell nixpkgs.libsodium;
-    ghc-lib-parser = nixpkgs.haskell.lib.overrideCabal (self.callHackage "ghc-lib-parser" "9.8.1.20231009" {}) (_drv: {
-      postPatch = let
-        original-a = "cabal-version: 2.0";
-        replacement-a = "cabal-version: 3.0";
-        original-b = "license: BSD3";
-        replacement-b = "license: BSD-3-Clause";
-        original-c =
-          "c-sources:\r\n        libraries/ghc-heap/cbits/HeapPrim.cmm";
-        replacement-c =
-          "cmm-sources:\r\n        libraries/ghc-heap/cbits/HeapPrim.cmm";
-      in ''
-        substituteInPlace ./ghc-lib-parser.cabal --replace \
-          '${original-a}' '${replacement-a}'
-        substituteInPlace ./ghc-lib-parser.cabal --replace \
-          '${original-b}' '${replacement-b}'
-        substituteInPlace ./ghc-lib-parser.cabal --replace \
-          '${original-c}' '${replacement-c}'
-      '';
-    });
-    shelly = nixpkgs.haskell.lib.doJailbreak super.shelly;
-    hourglass = nixpkgs.haskell.lib.dontCheck super.hourglass;
-    unliftio-core = nixpkgs.haskell.lib.doJailbreak super.unliftio-core;
-    tagged = self.callHackage "tagged" "0.8.8" {};
-    th-abstraction = self.callHackage "th-abstraction" "0.6.0.0" {};
-    th-lift = self.callHackage "th-lift" "0.8.4" {};
-    hspec-core = nixpkgs.haskell.lib.dontCheck (self.callHackage "hspec-core" "2.11.6" {});
-    hspec-expectations = self.callHackage "hspec-expectations" "0.8.4" {};
-    hspec-meta = self.callHackage "hspec-meta" "2.11.6" {};
-    hspec-discover = self.callHackage "hspec-discover" "2.11.6" {};
-    hspec = self.callHackage "hspec" "2.11.6" {};
-    lifted-base = nixpkgs.haskell.lib.dontCheck super.lifted-base;
-    bifunctors = self.callHackage "bifunctors" "5.6.1" {};
-    doctest = self.callHackage "doctest" "0.22.2" {};
-    semigroupoids = self.callHackage "semigroupoids" "6.0.0.1" {};
-    here = nixpkgs.haskell.lib.doJailbreak (self.callHackage "here" "1.2.14" {});
-    aeson = self.callHackage "aeson" "2.2.1.0" {};
-    haskell-src-meta = nixpkgs.haskell.lib.appendPatch (nixpkgs.haskell.lib.doJailbreak super.haskell-src-meta) (nixpkgs.fetchpatch {
-      url = "https://gitlab.haskell.org/ghc/head.hackage/-/raw/master/patches/haskell-src-meta-0.8.12.patch";
-      sha256 = "0wn0lnq522bhc65sw02jm448mg5ijdxwgs7gzp9xp6z8ir1a0bzr";
-    });
-
-  } // displays self);
-
-  # statically linking against haskell libs reduces closure size at the expense
-  # of startup/reload time, so we make it configurable
-  ihaskellExe = if staticExecutable
-    then nixpkgs.haskell.lib.justStaticExecutables haskellPackages.ihaskell
-    else nixpkgs.haskell.lib.enableSharedExecutables haskellPackages.ihaskell;
-  ihaskellEnv = haskellPackages.ghcWithPackages packages;
-  jupyterlab = nixpkgs.python3.withPackages (ps: [ ps.jupyterlab ps.notebook ] ++ pythonPackages ps);
-  ihaskellGhcLibFunc = exe: env: nixpkgs.writeShellScriptBin "ihaskell" ''
-    ${exe}/bin/ihaskell -l $(${env}/bin/ghc --print-libdir) "$@"
-  '';
-  ihaskellKernelFileFunc = ihaskellGhcLib: rtsopts: {
-    display_name = "Haskell";
-    argv = [
-      "${ihaskellGhcLib}/bin/ihaskell"
-      "kernel"
-      "{connection_file}"
-      "+RTS"
-    ] ++ (nixpkgs.lib.splitString " " rtsopts) ++ [
-      "-RTS"
-    ];
-    language = "haskell";
-  };
-  ihaskellKernelSpecFunc = ihaskellKernelFile: nixpkgs.runCommand "ihaskell-kernel" {} ''
-    export kerneldir=$out/kernels/haskell
-    mkdir -p $kerneldir
-    cp ${./html}/* $kerneldir
-    echo '${builtins.toJSON ihaskellKernelFile}' > $kerneldir/kernel.json
-  '';
-  ihaskellLabextension = nixpkgs.runCommand "ihaskell-labextension" {} ''
-    mkdir -p $out/labextensions/
-    ln -s ${./jupyterlab-ihaskell/labextension} $out/labextensions/jupyterlab-ihaskell
-  '';
-  ihaskellDataDirFunc = ihaskellKernelSpec: ihaskellLabextension: nixpkgs.buildEnv {
-    name = "ihaskell-data-dir";
-    paths = [ ihaskellKernelSpec ihaskellLabextension ];
-  };
-  ihaskellBuildEnvFunc = { ihaskellEnv, jupyterlab, systemPackages, ihaskellDataDir }: nixpkgs.buildEnv {
-    name = "ihaskell-with-packages";
-    nativeBuildInputs = [ nixpkgs.makeWrapper ];
-    paths = [ ihaskellEnv jupyterlab ];
-    postBuild = ''
-      for prg in $out/bin"/"*;do
-        if [[ -f $prg && -x $prg ]]; then
-          wrapProgram $prg \
-            --prefix PATH : "${nixpkgs.lib.makeBinPath ([ihaskellEnv] ++ (systemPackages nixpkgs))}" \
-            --prefix JUPYTER_PATH : "${ihaskellDataDir}"
-        fi
-      done
-    '';
-    passthru = {
-      inherit haskellPackages;
-      inherit ihaskellExe;
-      inherit ihaskellEnv;
-      inherit ihaskellOverlay;
-      inherit ihaskellLabextension;
-      inherit jupyterlab;
-      inherit ihaskellGhcLibFunc;
-      inherit ihaskellKernelFileFunc;
-      inherit ihaskellKernelSpecFunc;
-      inherit ihaskellDataDirFunc;
-      inherit ihaskellBuildEnvFunc;
-    };
-  };
-in ihaskellBuildEnvFunc {
-  inherit ihaskellEnv jupyterlab systemPackages;
-  ihaskellDataDir = let
-    ihaskellGhcLib = ihaskellGhcLibFunc ihaskellExe ihaskellEnv;
-    ihaskellKernelFile = ihaskellKernelFileFunc ihaskellGhcLib rtsopts;
-    ihaskellKernelSpec = ihaskellKernelSpecFunc ihaskellKernelFile;
-  in ihaskellDataDirFunc ihaskellKernelSpec ihaskellLabextension;
-}
diff --git a/release.nix b/release.nix
deleted file mode 100644
index d52d48fc..00000000
--- a/release.nix
+++ /dev/null
@@ -1,105 +0,0 @@
-{ compiler
-, nixpkgs ? import <nixpkgs> {}
-, packages ? (_: [])
-, pythonPackages ? (_: [])
-, rtsopts ? "-M3g -N2"
-, staticExecutable ? false
-, systemPackages ? (_: [])
-}:
-
-let
-  ihaskell-src = nixpkgs.nix-gitignore.gitignoreSource
-    [ "**/*.ipynb" "**/*.nix" "**/*.yaml" "**/*.yml" "**/\.*" "/Dockerfile" "/README.md" "/cabal.project" "/images" "/notebooks" "/test" "/requirements.txt" ]
-    ./.;
-  displays = self: builtins.listToAttrs (
-    map
-      (display: { name = "ihaskell-${display}"; value = self.callCabal2nix display "${ihaskell-src}/ihaskell-display/ihaskell-${display}" {}; })
-      [ "aeson" "blaze" "charts" "diagrams" "gnuplot" "graphviz" "hatex" "juicypixels" "magic" "plot" "rlangqq" "static-canvas" "widgets" ]);
-  haskellPackages = nixpkgs.haskell.packages."${compiler}".override (old: {
-    overrides = nixpkgs.lib.composeExtensions (old.overrides or (_: _: {})) ihaskellOverlay;
-  });
-
-  ihaskellOverlay = (self: super: {
-    ihaskell = nixpkgs.haskell.lib.overrideCabal (
-                     self.callCabal2nix "ihaskell" ihaskell-src {}) (_drv: {
-      preCheck = ''
-        export HOME=$TMPDIR/home
-        export PATH=$PWD/dist/build/ihaskell:$PATH
-        export GHC_PACKAGE_PATH=$PWD/dist/package.conf.inplace/:$GHC_PACKAGE_PATH
-      '';
-    });
-    ghc-parser     = self.callCabal2nix "ghc-parser" (builtins.path { path = ./ghc-parser; name = "ghc-parser-src"; }) {};
-    ipython-kernel = self.callCabal2nix "ipython-kernel" (builtins.path { path = ./ipython-kernel; name = "ipython-kernel-src"; }) {};
-  } // displays self);
-
-  # statically linking against haskell libs reduces closure size at the expense
-  # of startup/reload time, so we make it configurable
-  ihaskellExe = if staticExecutable
-    then nixpkgs.haskell.lib.justStaticExecutables haskellPackages.ihaskell
-    else nixpkgs.haskell.lib.enableSharedExecutables haskellPackages.ihaskell;
-  ihaskellEnv = haskellPackages.ghcWithPackages packages;
-  jupyterlab = nixpkgs.python3.withPackages (ps: [ ps.jupyterlab ps.notebook ] ++ pythonPackages ps);
-  ihaskellGhcLibFunc = exe: env: nixpkgs.writeShellScriptBin "ihaskell" ''
-    ${exe}/bin/ihaskell -l $(${env}/bin/ghc --print-libdir) "$@"
-  '';
-  ihaskellKernelFileFunc = ihaskellGhcLib: rtsopts: {
-    display_name = "Haskell";
-    argv = [
-      "${ihaskellGhcLib}/bin/ihaskell"
-      "kernel"
-      "{connection_file}"
-      "+RTS"
-    ] ++ (nixpkgs.lib.splitString " " rtsopts) ++ [
-      "-RTS"
-    ];
-    language = "haskell";
-  };
-  ihaskellKernelSpecFunc = ihaskellKernelFile: nixpkgs.runCommand "ihaskell-kernel" {} ''
-    export kerneldir=$out/kernels/haskell
-    mkdir -p $kerneldir
-    cp ${./html}/* $kerneldir
-    echo '${builtins.toJSON ihaskellKernelFile}' > $kerneldir/kernel.json
-  '';
-  ihaskellLabextension = nixpkgs.runCommand "ihaskell-labextension" {} ''
-    mkdir -p $out/labextensions/
-    ln -s ${./jupyterlab-ihaskell/labextension} $out/labextensions/jupyterlab-ihaskell
-  '';
-  ihaskellDataDirFunc = ihaskellKernelSpec: ihaskellLabextension: nixpkgs.buildEnv {
-    name = "ihaskell-data-dir";
-    paths = [ ihaskellKernelSpec ihaskellLabextension ];
-  };
-  ihaskellBuildEnvFunc = { ihaskellEnv, jupyterlab, systemPackages, ihaskellDataDir }: nixpkgs.buildEnv {
-    name = "ihaskell-with-packages";
-    nativeBuildInputs = [ nixpkgs.makeWrapper ];
-    paths = [ ihaskellEnv jupyterlab ];
-    postBuild = ''
-      for prg in $out/bin"/"*;do
-        if [[ -f $prg && -x $prg ]]; then
-          wrapProgram $prg \
-            --prefix PATH : "${nixpkgs.lib.makeBinPath ([ihaskellEnv] ++ (systemPackages nixpkgs))}" \
-            --prefix JUPYTER_PATH : "${ihaskellDataDir}"
-        fi
-      done
-    '';
-    passthru = {
-      inherit haskellPackages;
-      inherit ihaskellExe;
-      inherit ihaskellEnv;
-      inherit ihaskellOverlay;
-      inherit ihaskellLabextension;
-      inherit jupyterlab;
-      inherit ihaskellGhcLibFunc;
-      inherit ihaskellKernelFileFunc;
-      inherit ihaskellKernelSpecFunc;
-      inherit ihaskellDataDirFunc;
-      inherit ihaskellBuildEnvFunc;
-    };
-  };
-in ihaskellBuildEnvFunc {
-  inherit ihaskellEnv jupyterlab systemPackages;
-  ihaskellDataDir = let
-    ihaskellGhcLib = ihaskellGhcLibFunc ihaskellExe ihaskellEnv;
-    ihaskellKernelFile = ihaskellKernelFileFunc ihaskellGhcLib rtsopts;
-    ihaskellKernelSpec = ihaskellKernelSpecFunc ihaskellKernelFile;
-  in ihaskellDataDirFunc ihaskellKernelSpec ihaskellLabextension;
-}
diff --git a/stack-8.2.yaml b/stack-8.2.yaml
deleted file mode 100644
index fe683629..00000000
--- a/stack-8.2.yaml
+++ /dev/null
@@ -1,62 +0,0 @@
-resolver: lts-11.22
-
-flags: {}
-packages:
-    - .
-    - ./ipython-kernel
-    - ./ghc-parser
-    - ./ihaskell-display/ihaskell-aeson
-    - ./ihaskell-display/ihaskell-blaze
-    - ./ihaskell-display/ihaskell-charts
-    - ./ihaskell-display/ihaskell-diagrams
-    - ./ihaskell-display/ihaskell-gnuplot
-    - ./ihaskell-display/ihaskell-graphviz
-    - ./ihaskell-display/ihaskell-hatex
-    - ./ihaskell-display/ihaskell-juicypixels
-    - ./ihaskell-display/ihaskell-magic
-    - ./ihaskell-display/ihaskell-plot
-    - ./ihaskell-display/ihaskell-static-canvas
-    - ./ihaskell-display/ihaskell-widgets
-
-ghc-options:
-  # Eventually we want "$locals": -Wall -Werror
-  ghc-parser: -Wall -Werror
-  ihaskell: -Wall -Werror
-  ihaskell-widgets: -Wall -Werror
-
-allow-newer: true
-
-extra-deps:
-- Chart-cairo-1.9.1
-- cairo-0.13.6.0
-- cubicbezier-0.6.0.5
-- diagrams-1.4
-- diagrams-cairo-1.4.1
-- diagrams-contrib-1.4.2.1
-- diagrams-core-1.4.0.1
-- diagrams-lib-1.4.2
-- diagrams-solve-0.1.1
-- diagrams-svg-1.4.1.1
-- dual-tree-0.2.1
-- fast-math-1.0.2
-- glib-0.13.7.1
-- gtk2hs-buildtools-0.13.5.4
-- magic-1.1
-- mfsolve-0.3.2.0
-- pango-0.13.6.1
-- plot-0.2.3.9
-- static-canvas-0.2.0.3
-
-nix:
-  packages:
-    - blas
-    - cairo
-    - file
-    - gcc
-    - gfortran.cc.lib
-    - liblapack
-    - ncurses
-    - pango
-    - pkgconfig
-    - zeromq
-    - zlib
diff --git a/stack-8.4.yaml b/stack-8.4.yaml
deleted file mode 100644
index c158d227..00000000
--- a/stack-8.4.yaml
+++ /dev/null
@@ -1,49 +0,0 @@
-resolver: lts-12.26
-
-flags: {}
-packages:
-    - .
-    - ./ipython-kernel
-    - ./ghc-parser
-    - ./ihaskell-display/ihaskell-aeson
-    - ./ihaskell-display/ihaskell-blaze
-    - ./ihaskell-display/ihaskell-charts
-    - ./ihaskell-display/ihaskell-diagrams
-    - ./ihaskell-display/ihaskell-gnuplot
-    - ./ihaskell-display/ihaskell-hatex
-    - ./ihaskell-display/ihaskell-juicypixels
-    - ./ihaskell-display/ihaskell-magic
-    - ./ihaskell-display/ihaskell-plot
-    - ./ihaskell-display/ihaskell-static-canvas
-    - ./ihaskell-display/ihaskell-widgets
-
-extra-deps:
-- plot-0.2.3.9
-- Chart-cairo-1.9.1
-- Chart-1.9.4
-- diagrams-cairo-1.4.1
-- cairo-0.13.6.0
-- pango-0.13.6.1
-- glib-0.13.7.1
-- gtk2hs-buildtools-0.13.5.4
-- magic-1.1
-
-ghc-options:
-  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
-  ghc-parser: -Wall -Wpartial-fields -Werror
-  ihaskell: -Wall -Wpartial-fields -Werror
-  ihaskell-widgets: -Wall -Wpartial-fields -Werror
-
-nix:
-  packages:
-    - blas
-    - cairo
-    - file
-    - gcc
-    - gfortran.cc.lib
-    - liblapack
-    - ncurses
-    - pango
-    - pkgconfig
-    - zeromq
-    - zlib
diff --git a/stack-8.6.yaml b/stack-8.6.yaml
deleted file mode 100644
index 6a24fde1..00000000
--- a/stack-8.6.yaml
+++ /dev/null
@@ -1,48 +0,0 @@
-resolver: lts-14.27
-
-flags: {}
-packages:
-    - .
-    - ./ipython-kernel
-    - ./ghc-parser
-    - ./ihaskell-display/ihaskell-aeson
-    - ./ihaskell-display/ihaskell-blaze
-    - ./ihaskell-display/ihaskell-charts
-    - ./ihaskell-display/ihaskell-diagrams
-    - ./ihaskell-display/ihaskell-gnuplot
-    - ./ihaskell-display/ihaskell-hatex
-    - ./ihaskell-display/ihaskell-juicypixels
-    - ./ihaskell-display/ihaskell-magic
-    # - ./ihaskell-display/ihaskell-plot
-    # - ./ihaskell-display/ihaskell-static-canvas
-    - ./ihaskell-display/ihaskell-widgets
-
-extra-deps:
-- Chart-cairo-1.9.1
-- diagrams-cairo-1.4.1
-- cairo-0.13.6.0
-- pango-0.13.6.1
-- glib-0.13.7.1
-- gtk2hs-buildtools-0.13.5.4
-- magic-1.1
-# - plot-0.2.3.9
-
-ghc-options:
-  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
-  ghc-parser: -Wall -Wpartial-fields -Werror
-  ihaskell: -Wall -Wpartial-fields -Werror
-  ihaskell-widgets: -Wall -Wpartial-fields -Werror
-
-nix:
-  packages:
-    - blas
-    - cairo
-    - file
-    - gcc
-    - gfortran.cc.lib
-    - liblapack
-    - ncurses
-    - pango
-    - pkgconfig
-    - zeromq
-    - zlib
diff --git a/stack-8.8.yaml b/stack-8.8.yaml
deleted file mode 100644
index e8f87847..00000000
--- a/stack-8.8.yaml
+++ /dev/null
@@ -1,50 +0,0 @@
-resolver: lts-16.23
-
-flags: {}
-packages:
-    - .
-    - ./ipython-kernel
-    - ./ghc-parser
-    - ./ihaskell-display/ihaskell-aeson
-    - ./ihaskell-display/ihaskell-blaze
-    - ./ihaskell-display/ihaskell-charts
-    - ./ihaskell-display/ihaskell-diagrams
-    - ./ihaskell-display/ihaskell-gnuplot
-    - ./ihaskell-display/ihaskell-hatex
-    - ./ihaskell-display/ihaskell-juicypixels
-    - ./ihaskell-display/ihaskell-magic
-    - ./ihaskell-display/ihaskell-plot
-    # - ./ihaskell-display/ihaskell-static-canvas
-    - ./ihaskell-display/ihaskell-widgets
-
-extra-deps:
-- Chart-cairo-1.9.3
-- diagrams-cairo-1.4.1.1
-- cairo-0.13.10.0
-- pango-0.13.10.0
-- glib-0.13.10.0
-- gtk2hs-buildtools-0.13.10.0
-- magic-1.1
-- plot-0.2.3.11
-# - static-canvas-0.2.0.3
-- vinyl-0.13.0
-
-ghc-options:
-  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
-  # ghc-parser: -Wall -Wpartial-fields -Werror
-  # ihaskell: -Wall -Wpartial-fields -Werror
-  # ihaskell-widgets: -Wall -Wpartial-fields -Werror
-
-nix:
-  packages:
-    - blas
-    - cairo
-    - file
-    - gcc
-    - gfortran.cc.lib
-    - liblapack
-    - ncurses
-    - pango
-    - pkgconfig
-    - zeromq
-    - zlib
diff --git a/stack-9.0.yaml b/stack-9.0.yaml
deleted file mode 100644
index 2bb1ba38..00000000
--- a/stack-9.0.yaml
+++ /dev/null
@@ -1,48 +0,0 @@
-resolver: lts-19.23 # GHC 9.0.2
-
-flags: {}
-packages:
-    - .
-    - ./ipython-kernel
-    - ./ghc-parser
-    - ./ihaskell-display/ihaskell-aeson
-    - ./ihaskell-display/ihaskell-blaze
-    - ./ihaskell-display/ihaskell-charts
-    - ./ihaskell-display/ihaskell-diagrams
-    - ./ihaskell-display/ihaskell-gnuplot
-    - ./ihaskell-display/ihaskell-graphviz
-    - ./ihaskell-display/ihaskell-hatex
-    - ./ihaskell-display/ihaskell-juicypixels
-    - ./ihaskell-display/ihaskell-magic
-    - ./ihaskell-display/ihaskell-plot
-    # - ./ihaskell-display/ihaskell-static-canvas
-    - ./ihaskell-display/ihaskell-widgets
-
-extra-deps:
-- Chart-cairo-1.9.3
-- diagrams-cairo-1.4.2
-- cairo-0.13.8.2
-- pango-0.13.8.2
-- glib-0.13.8.2
-- plot-0.2.3.11
-- statestack-0.3
-
-ghc-options:
-  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
-  # ghc-parser: -Wall -Wpartial-fields -Werror
-  # ihaskell: -Wall -Wpartial-fields -Werror
-  # ihaskell-widgets: -Wall -Wpartial-fields -Werror
-
-nix:
-  packages:
-    - blas
-    - cairo
-    - file
-    - gcc
-    - gfortran.cc.lib
-    - liblapack
-    - ncurses
-    - pango
-    - pkgconfig
-    - zeromq
-    - zlib
diff --git a/stack-9.2.yaml b/stack-9.2.yaml
deleted file mode 100644
index b5219192..00000000
--- a/stack-9.2.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-resolver: lts-20.13
-
-flags: {}
-packages:
-    - .
-    - ./ipython-kernel
-    - ./ghc-parser
-    - ./ihaskell-display/ihaskell-aeson
-    - ./ihaskell-display/ihaskell-blaze
-    - ./ihaskell-display/ihaskell-charts
-    - ./ihaskell-display/ihaskell-diagrams
-    - ./ihaskell-display/ihaskell-gnuplot
-    - ./ihaskell-display/ihaskell-graphviz
-    - ./ihaskell-display/ihaskell-hatex
-    - ./ihaskell-display/ihaskell-juicypixels
-    - ./ihaskell-display/ihaskell-magic
-    - ./ihaskell-display/ihaskell-plot
-    # - ./ihaskell-display/ihaskell-static-canvas
-    - ./ihaskell-display/ihaskell-widgets
-
-ghc-options:
-  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
-  # ghc-parser: -Wall -Wpartial-fields -Werror
-  # ihaskell: -Wall -Wpartial-fields -Werror
-  # ihaskell-widgets: -Wall -Wpartial-fields -Werror
-
-nix:
-  enable: false
-  packages:
-    - blas
-    - cairo
-    - file
-    - gcc
-    - gfortran.cc.lib
-    - liblapack
-    - ncurses
-    - pango
-    - pkgconfig
-    - zeromq
-    - zlib
diff --git a/stack.yaml b/stack.yaml
index 897e8a1e..44d39e2f 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,31 +1,21 @@
-resolver: lts-21.6
+resolver: lts-21.21 # GHC 9.4.7
 
-flags: {}
 packages:
-    - .
-    - ./ipython-kernel
-    - ./ghc-parser
-    - ./ihaskell-display/ihaskell-aeson
-    - ./ihaskell-display/ihaskell-blaze
-    - ./ihaskell-display/ihaskell-charts
-    - ./ihaskell-display/ihaskell-diagrams
-    - ./ihaskell-display/ihaskell-gnuplot
-    - ./ihaskell-display/ihaskell-graphviz
-    - ./ihaskell-display/ihaskell-hatex
-    - ./ihaskell-display/ihaskell-juicypixels
-    - ./ihaskell-display/ihaskell-magic
-    - ./ihaskell-display/ihaskell-plot
-    # - ./ihaskell-display/ihaskell-static-canvas
-    - ./ihaskell-display/ihaskell-widgets
-
-extra-deps:
-- Chart-cairo-1.9.3
-- diagrams-cairo-1.4.2.1
-- cairo-0.13.10.0
-- pango-0.13.10.0
-- glib-0.13.10.0
-- plot-0.2.3.11
-- statestack-0.3.1.1
+- .
+- ./ipython-kernel
+- ./ghc-parser
+- ./ihaskell-display/ihaskell-aeson
+- ./ihaskell-display/ihaskell-blaze
+- ./ihaskell-display/ihaskell-charts
+- ./ihaskell-display/ihaskell-diagrams
+- ./ihaskell-display/ihaskell-gnuplot
+- ./ihaskell-display/ihaskell-graphviz
+- ./ihaskell-display/ihaskell-hatex
+- ./ihaskell-display/ihaskell-juicypixels
+- ./ihaskell-display/ihaskell-magic
+- ./ihaskell-display/ihaskell-plot
+# - ./ihaskell-display/ihaskell-static-canvas
+- ./ihaskell-display/ihaskell-widgets
 
 ghc-options:
   # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
@@ -33,27 +23,29 @@ ghc-options:
   # ihaskell: -Wall -Wpartial-fields -Werror
   # ihaskell-widgets: -Wall -Wpartial-fields -Werror
 
+extra-deps:
+- Chart-cairo-1.9.3
+
 nix:
   packages:
-    - blas
-    - cairo
-    - file
-    - fribidi
-    - gcc
-    - gfortran.cc.lib
-    - libdatrie
-    - liblapack
-    - libselinux
-    - libsepol
-    - libsodium # Needed by zeromq
-    - libthai
-    - ncurses
-    - pango
-    - pkg-config
-    - pcre
-    - pcre2
-    - pkgconfig
-    - util-linux
-    - xorg.libXdmcp
-    - zeromq
-    - zlib
+  - blas
+  - cairo
+  - expat
+  - file
+  - fribidi
+  - gcc
+  - gfortran.cc.lib
+  - libdatrie
+  - liblapack
+  - libselinux
+  - libsepol
+  - libthai
+  - ncurses
+  - pango
+  - pcre
+  - pcre2.dev
+  - pkg-config
+  - util-linux.dev
+  - xorg.libXdmcp
+  - zeromq
+  - zlib
diff --git a/stack-8.0.yaml b/stack/stack-8.0.yaml
similarity index 82%
rename from stack-8.0.yaml
rename to stack/stack-8.0.yaml
index 6f10d582..66dace69 100644
--- a/stack-8.0.yaml
+++ b/stack/stack-8.0.yaml
@@ -1,6 +1,5 @@
 resolver: lts-9.21
 
-flags: {}
 packages:
     - .
     - ./ipython-kernel
@@ -27,14 +26,14 @@ ghc-options:
 
 nix:
   packages:
-    - blas
-    - cairo
-    - file
-    - gcc
-    - gfortran.cc.lib
-    - liblapack
-    - ncurses
-    - pango
-    - pkgconfig
-    - zeromq
-    - zlib
+  - blas
+  - cairo
+  - file
+  - gcc
+  - gfortran.cc.lib
+  - liblapack
+  - ncurses
+  - pango
+  - pkg-config
+  - zeromq
+  - zlib
diff --git a/stack-8.10.yaml b/stack/stack-8.10.yaml
similarity index 51%
rename from stack-8.10.yaml
rename to stack/stack-8.10.yaml
index 2f8ec0fd..2072ebe2 100644
--- a/stack-8.10.yaml
+++ b/stack/stack-8.10.yaml
@@ -2,23 +2,22 @@
 resolver: lts-18.27
 allow-newer: true
 
-flags: {}
 packages:
-    - .
-    - ./ipython-kernel
-    - ./ghc-parser
-    - ./ihaskell-display/ihaskell-aeson
-    - ./ihaskell-display/ihaskell-blaze
-    - ./ihaskell-display/ihaskell-charts
-    - ./ihaskell-display/ihaskell-diagrams
-    - ./ihaskell-display/ihaskell-gnuplot
-    - ./ihaskell-display/ihaskell-graphviz
-    - ./ihaskell-display/ihaskell-hatex
-    - ./ihaskell-display/ihaskell-juicypixels
-    - ./ihaskell-display/ihaskell-magic
-    - ./ihaskell-display/ihaskell-plot
-    # - ./ihaskell-display/ihaskell-static-canvas
-    - ./ihaskell-display/ihaskell-widgets
+- ..
+- ../ipython-kernel
+- ../ghc-parser
+- ../ihaskell-display/ihaskell-aeson
+- ../ihaskell-display/ihaskell-blaze
+- ../ihaskell-display/ihaskell-charts
+- ../ihaskell-display/ihaskell-diagrams
+- ../ihaskell-display/ihaskell-gnuplot
+- ../ihaskell-display/ihaskell-graphviz
+- ../ihaskell-display/ihaskell-hatex
+- ../ihaskell-display/ihaskell-juicypixels
+- ../ihaskell-display/ihaskell-magic
+- ../ihaskell-display/ihaskell-plot
+# - ../ihaskell-display/ihaskell-static-canvas
+- ../ihaskell-display/ihaskell-widgets
 
 extra-deps:
 - active-0.2.0.14
@@ -49,14 +48,14 @@ ghc-options:
 
 nix:
   packages:
-    - blas
-    - cairo
-    - file
-    - gcc
-    - gfortran.cc.lib
-    - liblapack
-    - ncurses
-    - pango
-    - pkgconfig
-    - zeromq
-    - zlib
+  - blas
+  - cairo
+  - file
+  - gcc
+  - gfortran.cc.lib
+  - liblapack
+  - ncurses
+  - pango
+  - pkg-config
+  - zeromq
+  - zlib
diff --git a/stack/stack-8.10.yaml.lock b/stack/stack-8.10.yaml.lock
new file mode 100644
index 00000000..f43490fe
--- /dev/null
+++ b/stack/stack-8.10.yaml.lock
@@ -0,0 +1,138 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages:
+- completed:
+    hackage: active-0.2.0.14@sha256:e618aba4a7881eb85dc1585e0a01230af6b4fbab6693931e4a5d0d3a5b184406,1823
+    pantry-tree:
+      sha256: 9326ee3500f7bb1adea18f581dc51ebdb522677d8cddc847a506ba5d328ee723
+      size: 1017
+  original:
+    hackage: active-0.2.0.14
+- completed:
+    hackage: Chart-cairo-1.9.3@sha256:5d6f005b5d3d74453a979eb2c6a1777c92ce02eae9e019abbe03a0e008cb8aea,924
+    pantry-tree:
+      sha256: 204f29235d182cc8c8ab40d0a37387e78c1dadc684e190c85e1643521483e681
+      size: 238
+  original:
+    hackage: Chart-cairo-1.9.3
+- completed:
+    hackage: diagrams-1.4@sha256:3e36369e84115b900fd9dcb570672a188339a470eb19ca62170775cd835cf8ca,5483
+    pantry-tree:
+      sha256: 8f2ea432c67f4711446942e032be53ed7dc49c1b1dd7d26ff71fbd4d05a02c4d
+      size: 208
+  original:
+    hackage: diagrams-1.4
+- completed:
+    hackage: diagrams-cairo-1.4.1.1@sha256:8b62e90fcb0a2c9343f594940698a148b2e778b203f3297c0bed3097d34b559a,3801
+    pantry-tree:
+      sha256: de94736d9aa3f321e9d621667e41ac029f47fe9956ee625eb46920bd9c3c7f80
+      size: 721
+  original:
+    hackage: diagrams-cairo-1.4.1.1
+- completed:
+    hackage: diagrams-contrib-1.4.4@sha256:77c87ab5c780086eca845df233d3b6816a2aed82a80b7f4abe5ce1259801924b,4753
+    pantry-tree:
+      sha256: 6f1a006bf528662f4f34e02207571669af6dab6966c64c0558559dfc16c43bf8
+      size: 11387
+  original:
+    hackage: diagrams-contrib-1.4.4
+- completed:
+    hackage: diagrams-core-1.5.0@sha256:8ffd24eb97ce309b41c52e5fa3a8acee5e4063565919eb4d41abb5c219b3d49b,2971
+    pantry-tree:
+      sha256: 670806e0af1e31792557a3bc2c4ffe4c39929fea718c3071eb4702c4512c9795
+      size: 2018
+  original:
+    hackage: diagrams-core-1.5.0
+- completed:
+    hackage: diagrams-lib-1.4.4@sha256:1129be254377b926ce2e932113e4bd06256de878d163fbcbacacf1be97bdf3b0,8220
+    pantry-tree:
+      sha256: a96099f5e6e4c3236dd2c2dd301e5498a1dd4b968a05dcec144c46eb53e6d912
+      size: 11604
+  original:
+    hackage: diagrams-lib-1.4.4
+- completed:
+    hackage: diagrams-svg-1.4.3@sha256:407ff78cb7bd1f44c68b0059036186f17a281a053901e29d0139ab151e703247,3159
+    pantry-tree:
+      sha256: 53c2221ee415d9bfc2f0dd886b67b1edbfdb91f68e809b43cf0bb830fc870ad7
+      size: 475
+  original:
+    hackage: diagrams-svg-1.4.3
+- completed:
+    hackage: cairo-0.13.8.1@sha256:1938aaeb5d3504678d995774dfe870f6b66cbd43d336b692fa8779b23b2b67a9,4075
+    pantry-tree:
+      sha256: 8f6344da4c578a4dd3a49c333e2158b695bfae32a74d34a76bbc6e531b70c95c
+      size: 2830
+  original:
+    hackage: cairo-0.13.8.1
+- completed:
+    hackage: pango-0.13.8.1@sha256:877b121c0bf87c96d3619effae6751ecfd74b7f7f3227cf3fde012597aed5ed9,3917
+    pantry-tree:
+      sha256: eec456a3d16f1a9305196a86a7c49a6f2cfe1b041a50b02059dc4898a07a3bd9
+      size: 1506
+  original:
+    hackage: pango-0.13.8.1
+- completed:
+    hackage: glib-0.13.8.1@sha256:42670daf0c85309281e08ba8559df75daa2e3be642e79fdfa781bef5e59658b0,3156
+    pantry-tree:
+      sha256: 1167575db8823b7a9f5fbaebdbc0ea5cef54301e442754ec256ba9371bd388e7
+      size: 1625
+  original:
+    hackage: glib-0.13.8.1
+- completed:
+    hackage: gtk2hs-buildtools-0.13.8.3@sha256:207229eee7abff12aba2740b32131522086275e46f2e72a0f5bbc3cb781e9d4d,5304
+    pantry-tree:
+      sha256: 1f93c6dbf2573503c48019fdf9f4662dcac494beaecccaea1873ec901eb2152f
+      size: 3588
+  original:
+    hackage: gtk2hs-buildtools-0.13.8.3
+- completed:
+    hackage: plot-0.2.3.11@sha256:9564d62da798b74a5ab875996f45adf1c3071e161247faa9a9d1b036e6634a4a,4413
+    pantry-tree:
+      sha256: 2b9cb15fa582d3cdc9f43e6ffaf401e36535909b3620c5f54bd9b7cca5dfeb44
+      size: 2704
+  original:
+    hackage: plot-0.2.3.11
+- completed:
+    hackage: statestack-0.3@sha256:437941f253bc7a6d8321e67938667bae53d7765b256a45976accadd85f6e1703,1146
+    pantry-tree:
+      sha256: 5b0ba98ac695eccbba33aae8eccf2b6dd8aa3d16d38db65e9e4c231aaa5e4082
+      size: 272
+  original:
+    hackage: statestack-0.3
+- completed:
+    hackage: dual-tree-0.2.2.1@sha256:9ff31e461d873ae74ba51d93b454c0c4094726d7cb78a0c454394c965e83539d,2830
+    pantry-tree:
+      sha256: 70ea91862ac301648d63e9c69d0ff8154b1d3c9c632d224d4002c027861ec33e
+      size: 387
+  original:
+    hackage: dual-tree-0.2.2.1
+- completed:
+    hackage: monoid-extras-0.6@sha256:fabcab0a59ac48d8f271016cf8190b21969b202c760df2db85add2fef93d38b4,2197
+    pantry-tree:
+      sha256: b07d7eef465c7cbc2f5c8368ef98b8a746166cb6953c1f51643f9fba6ead99e0
+      size: 1187
+  original:
+    hackage: monoid-extras-0.6
+- completed:
+    hackage: svg-builder-0.1.1@sha256:87d09f56d5630ce126574e9f00d1adc7f53dda58270e689f5883431db3ba4b3a,1591
+    pantry-tree:
+      sha256: 1185b1d09ed186b0b3c5b2dc3d9422830c79c3eaa1342f751e5c66d07c397754
+      size: 535
+  original:
+    hackage: svg-builder-0.1.1
+- completed:
+    hackage: force-layout-0.4.0.6@sha256:9270e4333ac3bac705d1ed742523b31849dfa7df48a3721f98e2ac05bc07dbd0,1321
+    pantry-tree:
+      sha256: 062299837db65635bbdd24ad621bf08e25e0e67f0adfbf2a2021a4d65822f014
+      size: 276
+  original:
+    hackage: force-layout-0.4.0.6
+snapshots:
+- completed:
+    sha256: 79a786674930a89301b0e908fad2822a48882f3d01486117693c377b8edffdbe
+    size: 590102
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/27.yaml
+  original: lts-18.27
diff --git a/stack/stack-8.2.yaml b/stack/stack-8.2.yaml
new file mode 100644
index 00000000..e86c2897
--- /dev/null
+++ b/stack/stack-8.2.yaml
@@ -0,0 +1,61 @@
+resolver: lts-11.22
+
+packages:
+- .
+- ./ipython-kernel
+- ./ghc-parser
+- ./ihaskell-display/ihaskell-aeson
+- ./ihaskell-display/ihaskell-blaze
+- ./ihaskell-display/ihaskell-charts
+- ./ihaskell-display/ihaskell-diagrams
+- ./ihaskell-display/ihaskell-gnuplot
+- ./ihaskell-display/ihaskell-graphviz
+- ./ihaskell-display/ihaskell-hatex
+- ./ihaskell-display/ihaskell-juicypixels
+- ./ihaskell-display/ihaskell-magic
+- ./ihaskell-display/ihaskell-plot
+- ./ihaskell-display/ihaskell-static-canvas
+- ./ihaskell-display/ihaskell-widgets
+
+ghc-options:
+  # Eventually we want "$locals": -Wall -Werror
+  ghc-parser: -Wall -Werror
+  ihaskell: -Wall -Werror
+  ihaskell-widgets: -Wall -Werror
+
+allow-newer: true
+
+extra-deps:
+- Chart-cairo-1.9.1
+- cairo-0.13.6.0
+- cubicbezier-0.6.0.5
+- diagrams-1.4
+- diagrams-cairo-1.4.1
+- diagrams-contrib-1.4.2.1
+- diagrams-core-1.4.0.1
+- diagrams-lib-1.4.2
+- diagrams-solve-0.1.1
+- diagrams-svg-1.4.1.1
+- dual-tree-0.2.1
+- fast-math-1.0.2
+- glib-0.13.7.1
+- gtk2hs-buildtools-0.13.5.4
+- magic-1.1
+- mfsolve-0.3.2.0
+- pango-0.13.6.1
+- plot-0.2.3.9
+- static-canvas-0.2.0.3
+
+nix:
+  packages:
+  - blas
+  - cairo
+  - file
+  - gcc
+  - gfortran.cc.lib
+  - liblapack
+  - ncurses
+  - pango
+  - pkg-config
+  - zeromq
+  - zlib
diff --git a/stack/stack-8.2.yaml.lock b/stack/stack-8.2.yaml.lock
new file mode 100644
index 00000000..9f49de8d
--- /dev/null
+++ b/stack/stack-8.2.yaml.lock
@@ -0,0 +1,103 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages:
+- completed:
+    hackage: static-canvas-0.2.0.3@sha256:3ad170c6efbd26b981fe66f4c4a85e515c200c675e3f2c6603da7d64e84bc8f5,1768
+    pantry-tree:
+      sha256: b61e591e6028dc284ed5ed22f9bab9fcfe9034288741dcc26d0eae79b140031c
+      size: 563
+  original:
+    hackage: static-canvas-0.2.0.3
+- completed:
+    hackage: diagrams-1.4@sha256:3e36369e84115b900fd9dcb570672a188339a470eb19ca62170775cd835cf8ca,5483
+    pantry-tree:
+      sha256: 8f2ea432c67f4711446942e032be53ed7dc49c1b1dd7d26ff71fbd4d05a02c4d
+      size: 208
+  original:
+    hackage: diagrams-1.4
+- completed:
+    hackage: diagrams-cairo-1.4@sha256:268fc389290424fbb0c4c207e4e09cb1ef7e652269ea63cd3d746da2f8a041c0,3869
+    pantry-tree:
+      sha256: f94fe112eeb6d0b1be6af93c56bfe8f16d0ea63a99b50c9aa38476a8363ae420
+      size: 721
+  original:
+    hackage: diagrams-cairo-1.4
+- completed:
+    hackage: diagrams-lib-1.4.2@sha256:3ac3821d32a87501328c34d9f4f6ee1ee7b50c3a3ca0ddf4c6beeb1fa847313b,8104
+    pantry-tree:
+      sha256: 5d375f02f07a6fea645becec4f94c0ff5866791168cbdb632eccc8c7c3f01eb3
+      size: 11529
+  original:
+    hackage: diagrams-lib-1.4.2
+- completed:
+    hackage: magic-1.1@sha256:3a31ca1c49fa5f6a857f647471739bd240a6020af6ae43e71fb72201fc482fa2,928
+    pantry-tree:
+      sha256: 8fd594932f36cdf6a93266c48248a6c516d2aa237cd023eed6935ccee7ed230b
+      size: 535
+  original:
+    hackage: magic-1.1
+- completed:
+    hackage: diagrams-contrib-1.4.2.1@sha256:553feab6969b3a65169bce2a548fb415b0e617baae9f72324a373030a825fc0a,4501
+    pantry-tree:
+      sha256: f803b132eceba65ef98425d1205c0031183660c60c44d52e2bea43d221c61328
+      size: 10858
+  original:
+    hackage: diagrams-contrib-1.4.2.1
+- completed:
+    hackage: diagrams-core-1.4.0.1@sha256:a60809ab07c9977d0c6fbbaeeabaa6df44e751b6c9ef2cd1a9b1beb1e9c87c37,2888
+    pantry-tree:
+      sha256: 45703e055dcfbc3c26939fddb6fe8bdf0b271f8d0992fd7f6ce1d366f190e519
+      size: 2018
+  original:
+    hackage: diagrams-core-1.4.0.1
+- completed:
+    hackage: diagrams-solve-0.1.1@sha256:8ed66891bb42f9cd5e77b02a0f8ebaa91a2363a82a007313f90c7f57806688fa,1713
+    pantry-tree:
+      sha256: eb09d6fe6c342061bc83bbdbe702692eae33b7d7e691a29e7112499a537494d3
+      size: 469
+  original:
+    hackage: diagrams-solve-0.1.1
+- completed:
+    hackage: diagrams-svg-1.4.1.1@sha256:a33bc07c73d4051230203a7bdbebbbdc4d5011c0efaa3fef9cb9afa65e120119,3104
+    pantry-tree:
+      sha256: 63a3f42f4866fa6cd954456c3ac5e58337fba4ba0bd383bd375751932a366c4c
+      size: 475
+  original:
+    hackage: diagrams-svg-1.4.1.1
+- completed:
+    hackage: dual-tree-0.2.1@sha256:842d3190984106fac7980a7320568b2dcd4145460a9299a05c8d078d4a79de58,2686
+    pantry-tree:
+      sha256: f7efa5a7dbdbb70d4df51c299c27ba1909a86f02717a4a9e952dcaeb73f0fb31
+      size: 387
+  original:
+    hackage: dual-tree-0.2.1
+- completed:
+    hackage: cubicbezier-0.6.0.5@sha256:a0e96070684203c828882d709e165f6adc89aa8e2ffd482bd14184df73c365f7,2293
+    pantry-tree:
+      sha256: 083acda7f3f4516f509ee85bc7ffd9aa91b2b0f3f40e3ccdeb94cc7f465ef82a
+      size: 1029
+  original:
+    hackage: cubicbezier-0.6.0.5
+- completed:
+    hackage: mfsolve-0.3.2.0@sha256:b63176f6adeb4ffa021a7c67211aa46ab101715cc592adaade1233cc92a45342,1196
+    pantry-tree:
+      sha256: d200c397b5770a9d8161fb023d4d0f13aa65b3d5953845f6449b4132bfb46168
+      size: 262
+  original:
+    hackage: mfsolve-0.3.2.0
+- completed:
+    hackage: fast-math-1.0.2@sha256:91181eb836e54413cc5a841e797c42b2264954e893ea530b6fc4da0dccf6a8b7,1387
+    pantry-tree:
+      sha256: f22194924e26d3a27faef9cc9943ebb703c508d8ee9c9c7507618e39d62853af
+      size: 421
+  original:
+    hackage: fast-math-1.0.2
+snapshots:
+- completed:
+    sha256: 341870ac98d8a9f8f77c4adf2e9e0b22063e264a7fbeb4c85b7af5f380dac60e
+    size: 527836
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/11/22.yaml
+  original: lts-11.22
diff --git a/stack/stack-8.4.yaml b/stack/stack-8.4.yaml
new file mode 100644
index 00000000..4879abbb
--- /dev/null
+++ b/stack/stack-8.4.yaml
@@ -0,0 +1,48 @@
+resolver: lts-12.26
+
+packages:
+- .
+- ./ipython-kernel
+- ./ghc-parser
+- ./ihaskell-display/ihaskell-aeson
+- ./ihaskell-display/ihaskell-blaze
+- ./ihaskell-display/ihaskell-charts
+- ./ihaskell-display/ihaskell-diagrams
+- ./ihaskell-display/ihaskell-gnuplot
+- ./ihaskell-display/ihaskell-hatex
+- ./ihaskell-display/ihaskell-juicypixels
+- ./ihaskell-display/ihaskell-magic
+- ./ihaskell-display/ihaskell-plot
+- ./ihaskell-display/ihaskell-static-canvas
+- ./ihaskell-display/ihaskell-widgets
+
+extra-deps:
+- plot-0.2.3.9
+- Chart-cairo-1.9.1
+- Chart-1.9.4
+- diagrams-cairo-1.4.1
+- cairo-0.13.6.0
+- pango-0.13.6.1
+- glib-0.13.7.1
+- gtk2hs-buildtools-0.13.5.4
+- magic-1.1
+
+ghc-options:
+  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
+  ghc-parser: -Wall -Wpartial-fields -Werror
+  ihaskell: -Wall -Wpartial-fields -Werror
+  ihaskell-widgets: -Wall -Wpartial-fields -Werror
+
+nix:
+  packages:
+  - blas
+  - cairo
+  - file
+  - gcc
+  - gfortran.cc.lib
+  - liblapack
+  - ncurses
+  - pango
+  - pkg-config
+  - zeromq
+  - zlib
diff --git a/stack/stack-8.4.yaml.lock b/stack/stack-8.4.yaml.lock
new file mode 100644
index 00000000..2c68c6f8
--- /dev/null
+++ b/stack/stack-8.4.yaml.lock
@@ -0,0 +1,40 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages:
+- completed:
+    hackage: magic-1.1@sha256:3a31ca1c49fa5f6a857f647471739bd240a6020af6ae43e71fb72201fc482fa2,928
+    pantry-tree:
+      sha256: 8fd594932f36cdf6a93266c48248a6c516d2aa237cd023eed6935ccee7ed230b
+      size: 535
+  original:
+    hackage: magic-1.1
+- completed:
+    hackage: Chart-1.9@sha256:f41568b6b3704f66c2ec163295b430ab7d798f91de426c2d5aba747d1135cd9b,2855
+    pantry-tree:
+      sha256: aaf8b3f35af0012324865cb24c7989dfc794e8dab3eb2152e949cf5243a451ca
+      size: 3031
+  original:
+    hackage: Chart-1.9
+- completed:
+    hackage: Chart-cairo-1.9@sha256:82875639be230c9406dbea650647b2dc94b11060160d6dad2c98551bb23d544f,877
+    pantry-tree:
+      sha256: 3eef9a2fdb682a95f5a60e66258d5b6036e9b8c19a7260f626ddda2d30113055
+      size: 238
+  original:
+    hackage: Chart-cairo-1.9
+- completed:
+    hackage: plot-0.2.3.9@sha256:85d157a5c1fef7068ffb74137bb56475f18c93c35f57bf76b38d95d46930fed0,4342
+    pantry-tree:
+      sha256: bc80948074253bd37c2b02dbae92b8cf28474f26ae6edbb5ec34cd6b5445e7f9
+      size: 2704
+  original:
+    hackage: plot-0.2.3.9
+snapshots:
+- completed:
+    sha256: 95f014df58d0679b1c4a2b7bf2b652b61da8d30de5f571abb0d59015ef678646
+    size: 509471
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/12/26.yaml
+  original: lts-12.26
diff --git a/stack/stack-8.6.yaml b/stack/stack-8.6.yaml
new file mode 100644
index 00000000..c95cdac3
--- /dev/null
+++ b/stack/stack-8.6.yaml
@@ -0,0 +1,47 @@
+resolver: lts-14.27
+
+packages:
+- ..
+- ../ipython-kernel
+- ../ghc-parser
+- ../ihaskell-display/ihaskell-aeson
+- ../ihaskell-display/ihaskell-blaze
+- ../ihaskell-display/ihaskell-charts
+- ../ihaskell-display/ihaskell-diagrams
+- ../ihaskell-display/ihaskell-gnuplot
+- ../ihaskell-display/ihaskell-hatex
+- ../ihaskell-display/ihaskell-juicypixels
+- ../ihaskell-display/ihaskell-magic
+# - ../ihaskell-display/ihaskell-plot
+# - ../ihaskell-display/ihaskell-static-canvas
+- ../ihaskell-display/ihaskell-widgets
+
+extra-deps:
+- Chart-cairo-1.9.1
+- diagrams-cairo-1.4.1
+- cairo-0.13.6.0
+- pango-0.13.6.1
+- glib-0.13.7.1
+- gtk2hs-buildtools-0.13.5.4
+- magic-1.1
+# - plot-0.2.3.9
+
+ghc-options:
+  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
+  ghc-parser: -Wall -Wpartial-fields -Werror
+  ihaskell: -Wall -Wpartial-fields -Werror
+  ihaskell-widgets: -Wall -Wpartial-fields -Werror
+
+nix:
+  packages:
+  - blas
+  - cairo
+  - file
+  - gcc
+  - gfortran.cc.lib
+  - liblapack
+  - ncurses
+  - pango
+  - pkg-config
+  - zeromq
+  - zlib
diff --git a/stack/stack-8.6.yaml.lock b/stack/stack-8.6.yaml.lock
new file mode 100644
index 00000000..f60eb655
--- /dev/null
+++ b/stack/stack-8.6.yaml.lock
@@ -0,0 +1,61 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages:
+- completed:
+    hackage: Chart-cairo-1.9.1@sha256:85605a4663f319e482bbd208c1e44c3cc8e0ec094fcd41b6afa3db4ce60635b0,925
+    pantry-tree:
+      sha256: 832739931c5d84c3c7b357782dd75cda9548a496f0be21cd1163e2b5e14fd89c
+      size: 238
+  original:
+    hackage: Chart-cairo-1.9.1
+- completed:
+    hackage: diagrams-cairo-1.4.1@sha256:e08f15a15146da9222344fbc433ccd6103c0a7f1e9dfe21bb1e3d3e36ad83947,3820
+    pantry-tree:
+      sha256: d046241de911d534c4b554d24090412cedeffb46e92cb5fb3884b5c667f5fc72
+      size: 721
+  original:
+    hackage: diagrams-cairo-1.4.1
+- completed:
+    hackage: cairo-0.13.6.0@sha256:a9122d48957a2dbb5a177e5068b850efa1e99bb22c68eb2571165c3c945a8dd6,4187
+    pantry-tree:
+      sha256: 180df55408086398e9901a6bcb2720da6fcecac5f57abcdb4df1251a686f1bb7
+      size: 2830
+  original:
+    hackage: cairo-0.13.6.0
+- completed:
+    hackage: pango-0.13.6.1@sha256:177c9b6d865dc8f1634742497c6807a7c37a11e86c0dc93fbc047981d546738a,3881
+    pantry-tree:
+      sha256: 216bb39cdc265804f6ddd30c00c82ab156c17dcf8577b85527c287a21b4cb9fb
+      size: 1506
+  original:
+    hackage: pango-0.13.6.1
+- completed:
+    hackage: glib-0.13.7.1@sha256:b517bbbc46f8bd72a8c97fb1d6769705a9b0d006f7cff8b3dc85948511817b11,3120
+    pantry-tree:
+      sha256: d7218c2ed9890d7b07030601980f62a57d5e888f656db5f32c3017ec7551a0d2
+      size: 1625
+  original:
+    hackage: glib-0.13.7.1
+- completed:
+    hackage: gtk2hs-buildtools-0.13.5.4@sha256:0f18b0103fa7a3cbc28edc6a97bdaf08e1f9bd273ef26d2ad498630ec6d0ac9c,5288
+    pantry-tree:
+      sha256: df6fdd3aaf8b9d3dd420b5c5906751d7399f1999607b396141d1493c76472e1b
+      size: 3588
+  original:
+    hackage: gtk2hs-buildtools-0.13.5.4
+- completed:
+    hackage: magic-1.1@sha256:3a31ca1c49fa5f6a857f647471739bd240a6020af6ae43e71fb72201fc482fa2,928
+    pantry-tree:
+      sha256: 8fd594932f36cdf6a93266c48248a6c516d2aa237cd023eed6935ccee7ed230b
+      size: 535
+  original:
+    hackage: magic-1.1
+snapshots:
+- completed:
+    sha256: 7ea31a280c56bf36ff591a7397cc384d0dff622e7f9e4225b47d8980f019a0f0
+    size: 524996
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/27.yaml
+  original: lts-14.27
diff --git a/stack/stack-8.8.yaml b/stack/stack-8.8.yaml
new file mode 100644
index 00000000..533c43ba
--- /dev/null
+++ b/stack/stack-8.8.yaml
@@ -0,0 +1,49 @@
+resolver: lts-16.31 # GHC 8.8.4
+
+packages:
+- ..
+- ../ipython-kernel
+- ../ghc-parser
+- ../ihaskell-display/ihaskell-aeson
+- ../ihaskell-display/ihaskell-blaze
+- ../ihaskell-display/ihaskell-charts
+- ../ihaskell-display/ihaskell-diagrams
+- ../ihaskell-display/ihaskell-gnuplot
+- ../ihaskell-display/ihaskell-hatex
+- ../ihaskell-display/ihaskell-juicypixels
+- ../ihaskell-display/ihaskell-magic
+- ../ihaskell-display/ihaskell-plot
+# - ../ihaskell-display/ihaskell-static-canvas
+- ../ihaskell-display/ihaskell-widgets
+
+extra-deps:
+- Chart-cairo-1.9.3
+- diagrams-cairo-1.4.1.1
+- cairo-0.13.10.0
+- pango-0.13.10.0
+- glib-0.13.10.0
+- gtk2hs-buildtools-0.13.10.0
+- magic-1.1
+- plot-0.2.3.11
+# - static-canvas-0.2.0.3
+- vinyl-0.13.0
+
+ghc-options:
+  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
+  # ghc-parser: -Wall -Wpartial-fields -Werror
+  # ihaskell: -Wall -Wpartial-fields -Werror
+  # ihaskell-widgets: -Wall -Wpartial-fields -Werror
+
+nix:
+  packages:
+  - blas
+  - cairo
+  - file
+  - gcc
+  - gfortran.cc.lib
+  - liblapack
+  - ncurses
+  - pango
+  - pkg-config
+  - zeromq
+  - zlib
diff --git a/stack/stack-8.8.yaml.lock b/stack/stack-8.8.yaml.lock
new file mode 100644
index 00000000..37a6353d
--- /dev/null
+++ b/stack/stack-8.8.yaml.lock
@@ -0,0 +1,75 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages:
+- completed:
+    hackage: Chart-cairo-1.9.3@sha256:5d6f005b5d3d74453a979eb2c6a1777c92ce02eae9e019abbe03a0e008cb8aea,924
+    pantry-tree:
+      sha256: 204f29235d182cc8c8ab40d0a37387e78c1dadc684e190c85e1643521483e681
+      size: 238
+  original:
+    hackage: Chart-cairo-1.9.3
+- completed:
+    hackage: diagrams-cairo-1.4.1.1@sha256:8b62e90fcb0a2c9343f594940698a148b2e778b203f3297c0bed3097d34b559a,3801
+    pantry-tree:
+      sha256: de94736d9aa3f321e9d621667e41ac029f47fe9956ee625eb46920bd9c3c7f80
+      size: 721
+  original:
+    hackage: diagrams-cairo-1.4.1.1
+- completed:
+    hackage: cairo-0.13.10.0@sha256:388f39af90d50b920cad70612046041a7ffd7f5b60721862c0c797ecddf7e902,4153
+    pantry-tree:
+      sha256: a5d7014b0df2600377d061185b104f755274935554e723e2b7b600b85ffc7ae2
+      size: 2831
+  original:
+    hackage: cairo-0.13.10.0
+- completed:
+    hackage: pango-0.13.10.0@sha256:4c7fc6187aadc2f3905a8fae7318ceccbb2af88134922536e3f4cae8640978dc,4081
+    pantry-tree:
+      sha256: acff0fc47176a959f14703e86704a0b5935aaabe84db245d03086061879179cf
+      size: 1506
+  original:
+    hackage: pango-0.13.10.0
+- completed:
+    hackage: glib-0.13.10.0@sha256:e136db5cb19cbec17f823e919a0b44c12e50a90296d03c9d0c54761200611267,3171
+    pantry-tree:
+      sha256: 2e513e6a9b5d5fa1603f832bfda6dee4cb3d77425aff4e9ec5a38682c8818d8b
+      size: 1625
+  original:
+    hackage: glib-0.13.10.0
+- completed:
+    hackage: gtk2hs-buildtools-0.13.10.0@sha256:ae8d2779835e29eb72f2ab1697901dba23adc45ccf197c7a51daaa5056869644,5305
+    pantry-tree:
+      sha256: 059d57676c2557bbf31c93189fb983ae0a7747fec8830395f88f4badfb90c12d
+      size: 3588
+  original:
+    hackage: gtk2hs-buildtools-0.13.10.0
+- completed:
+    hackage: magic-1.1@sha256:3a31ca1c49fa5f6a857f647471739bd240a6020af6ae43e71fb72201fc482fa2,928
+    pantry-tree:
+      sha256: 8fd594932f36cdf6a93266c48248a6c516d2aa237cd023eed6935ccee7ed230b
+      size: 535
+  original:
+    hackage: magic-1.1
+- completed:
+    hackage: plot-0.2.3.11@sha256:9564d62da798b74a5ab875996f45adf1c3071e161247faa9a9d1b036e6634a4a,4413
+    pantry-tree:
+      sha256: 2b9cb15fa582d3cdc9f43e6ffaf401e36535909b3620c5f54bd9b7cca5dfeb44
+      size: 2704
+  original:
+    hackage: plot-0.2.3.11
+- completed:
+    hackage: vinyl-0.13.0@sha256:0f247cd3f8682b30881a07de18e6fec52d540646fbcb328420049cc8d63cd407,3724
+    pantry-tree:
+      sha256: 860fb95820b595161cdbdec5f376100ebae2d14e5ef0dbe311546202f7525d01
+      size: 1857
+  original:
+    hackage: vinyl-0.13.0
+snapshots:
+- completed:
+    sha256: 637fb77049b25560622a224845b7acfe81a09fdb6a96a3c75997a10b651667f6
+    size: 534126
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/16/31.yaml
+  original: lts-16.31
diff --git a/stack/stack-9.0.yaml b/stack/stack-9.0.yaml
new file mode 100644
index 00000000..bd4b688c
--- /dev/null
+++ b/stack/stack-9.0.yaml
@@ -0,0 +1,47 @@
+resolver: lts-19.33 # GHC 9.0.2
+
+packages:
+- ..
+- ../ipython-kernel
+- ../ghc-parser
+- ../ihaskell-display/ihaskell-aeson
+- ../ihaskell-display/ihaskell-blaze
+- ../ihaskell-display/ihaskell-charts
+- ../ihaskell-display/ihaskell-diagrams
+- ../ihaskell-display/ihaskell-gnuplot
+- ../ihaskell-display/ihaskell-graphviz
+- ../ihaskell-display/ihaskell-hatex
+- ../ihaskell-display/ihaskell-juicypixels
+- ../ihaskell-display/ihaskell-magic
+- ../ihaskell-display/ihaskell-plot
+# - ../ihaskell-display/ihaskell-static-canvas
+- ../ihaskell-display/ihaskell-widgets
+
+extra-deps:
+- Chart-cairo-1.9.3
+- diagrams-cairo-1.4.2
+- cairo-0.13.8.2
+- pango-0.13.8.2
+- glib-0.13.8.2
+- plot-0.2.3.11
+- statestack-0.3
+
+ghc-options:
+  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
+  # ghc-parser: -Wall -Wpartial-fields -Werror
+  # ihaskell: -Wall -Wpartial-fields -Werror
+  # ihaskell-widgets: -Wall -Wpartial-fields -Werror
+
+nix:
+  packages:
+  - blas
+  - cairo
+  - file
+  - gcc
+  - gfortran.cc.lib
+  - liblapack
+  - ncurses
+  - pango
+  - pkg-config
+  - zeromq
+  - zlib
diff --git a/stack/stack-9.0.yaml.lock b/stack/stack-9.0.yaml.lock
new file mode 100644
index 00000000..663d354f
--- /dev/null
+++ b/stack/stack-9.0.yaml.lock
@@ -0,0 +1,61 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages:
+- completed:
+    hackage: Chart-cairo-1.9.3@sha256:5d6f005b5d3d74453a979eb2c6a1777c92ce02eae9e019abbe03a0e008cb8aea,924
+    pantry-tree:
+      sha256: 204f29235d182cc8c8ab40d0a37387e78c1dadc684e190c85e1643521483e681
+      size: 238
+  original:
+    hackage: Chart-cairo-1.9.3
+- completed:
+    hackage: diagrams-cairo-1.4.2@sha256:42807c226188653ab668baceab8fa2245149ed1fc9df595f6e77613ed1259424,3799
+    pantry-tree:
+      sha256: 02aadeb755a93b3a777c6efb597ef33a5a5c2ebcf28e4de7404ce8f1c23e7f1c
+      size: 721
+  original:
+    hackage: diagrams-cairo-1.4.2
+- completed:
+    hackage: cairo-0.13.8.2@sha256:ef1709c3c4d2c6d68a9a51d9f220dccc0745f6468d2d0868c15a7ecdf8f325a1,4078
+    pantry-tree:
+      sha256: d6a9b3a15bc2e7b53fda331279cfdbc299fbf0c4be2ee8c1b6b79b924b6fdeb4
+      size: 2830
+  original:
+    hackage: cairo-0.13.8.2
+- completed:
+    hackage: pango-0.13.8.2@sha256:d4057ebddade4cde3e25d7755b5e030e7a7e56fe7365afd37916a7bba46d3fd9,3917
+    pantry-tree:
+      sha256: 10c335853e1d43e0b7426b33e8ddbdb90b3e318ebec4d58f0726a2f4cfb2e1c9
+      size: 1506
+  original:
+    hackage: pango-0.13.8.2
+- completed:
+    hackage: glib-0.13.8.2@sha256:f44b829e741b3c3244d523f60b058701dfc067ff64c2ba61d43be4cccfc2663d,3156
+    pantry-tree:
+      sha256: 2442a22152231a94e2f1ecfe7ddc0f4e5fb2d5ae116b371508a448bd3312ef06
+      size: 1625
+  original:
+    hackage: glib-0.13.8.2
+- completed:
+    hackage: plot-0.2.3.11@sha256:9564d62da798b74a5ab875996f45adf1c3071e161247faa9a9d1b036e6634a4a,4413
+    pantry-tree:
+      sha256: 2b9cb15fa582d3cdc9f43e6ffaf401e36535909b3620c5f54bd9b7cca5dfeb44
+      size: 2704
+  original:
+    hackage: plot-0.2.3.11
+- completed:
+    hackage: statestack-0.3@sha256:437941f253bc7a6d8321e67938667bae53d7765b256a45976accadd85f6e1703,1146
+    pantry-tree:
+      sha256: 5b0ba98ac695eccbba33aae8eccf2b6dd8aa3d16d38db65e9e4c231aaa5e4082
+      size: 272
+  original:
+    hackage: statestack-0.3
+snapshots:
+- completed:
+    sha256: 6d1532d40621957a25bad5195bfca7938e8a06d923c91bc52aa0f3c41181f2d4
+    size: 619204
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/33.yaml
+  original: lts-19.33
diff --git a/stack/stack-9.2.yaml b/stack/stack-9.2.yaml
new file mode 100644
index 00000000..dbe55a22
--- /dev/null
+++ b/stack/stack-9.2.yaml
@@ -0,0 +1,38 @@
+resolver: lts-20.26 # GHC 9.2.8
+
+packages:
+- ..
+- ../ipython-kernel
+- ../ghc-parser
+- ../ihaskell-display/ihaskell-aeson
+- ../ihaskell-display/ihaskell-blaze
+- ../ihaskell-display/ihaskell-charts
+- ../ihaskell-display/ihaskell-diagrams
+- ../ihaskell-display/ihaskell-gnuplot
+- ../ihaskell-display/ihaskell-graphviz
+- ../ihaskell-display/ihaskell-hatex
+- ../ihaskell-display/ihaskell-juicypixels
+- ../ihaskell-display/ihaskell-magic
+- ../ihaskell-display/ihaskell-plot
+# - ../ihaskell-display/ihaskell-static-canvas
+- ../ihaskell-display/ihaskell-widgets
+
+ghc-options:
+  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
+  # ghc-parser: -Wall -Wpartial-fields -Werror
+  # ihaskell: -Wall -Wpartial-fields -Werror
+  # ihaskell-widgets: -Wall -Wpartial-fields -Werror
+
+nix:
+  packages:
+  - blas
+  - cairo
+  - file
+  - gcc
+  - gfortran.cc.lib
+  - liblapack
+  - ncurses
+  - pango
+  - pkg-config
+  - zeromq
+  - zlib
diff --git a/stack/stack-9.2.yaml.lock b/stack/stack-9.2.yaml.lock
new file mode 100644
index 00000000..ea5a8500
--- /dev/null
+++ b/stack/stack-9.2.yaml.lock
@@ -0,0 +1,12 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages: []
+snapshots:
+- completed:
+    sha256: 5a59b2a405b3aba3c00188453be172b85893cab8ebc352b1ef58b0eae5d248a2
+    size: 650475
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/26.yaml
+  original: lts-20.26
diff --git a/stack/stack-9.4.yaml b/stack/stack-9.4.yaml
new file mode 100644
index 00000000..11208f32
--- /dev/null
+++ b/stack/stack-9.4.yaml
@@ -0,0 +1,51 @@
+resolver: lts-21.21 # GHC 9.4.7
+
+packages:
+- ..
+- ../ipython-kernel
+- ../ghc-parser
+- ../ihaskell-display/ihaskell-aeson
+- ../ihaskell-display/ihaskell-blaze
+- ../ihaskell-display/ihaskell-charts
+- ../ihaskell-display/ihaskell-diagrams
+- ../ihaskell-display/ihaskell-gnuplot
+- ../ihaskell-display/ihaskell-graphviz
+- ../ihaskell-display/ihaskell-hatex
+- ../ihaskell-display/ihaskell-juicypixels
+- ../ihaskell-display/ihaskell-magic
+- ../ihaskell-display/ihaskell-plot
+# - ../ihaskell-display/ihaskell-static-canvas
+- ../ihaskell-display/ihaskell-widgets
+
+ghc-options:
+  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
+  # ghc-parser: -Wall -Wpartial-fields -Werror
+  # ihaskell: -Wall -Wpartial-fields -Werror
+  # ihaskell-widgets: -Wall -Wpartial-fields -Werror
+
+extra-deps:
+- Chart-cairo-1.9.3
+
+nix:
+  packages:
+  - blas
+  - cairo
+  - expat
+  - file
+  - fribidi
+  - gcc
+  - gfortran.cc.lib
+  - libdatrie
+  - liblapack
+  - libselinux
+  - libsepol
+  - libthai
+  - ncurses
+  - pango
+  - pcre
+  - pcre2.dev
+  - pkg-config
+  - util-linux.dev
+  - xorg.libXdmcp
+  - zeromq
+  - zlib
diff --git a/stack/stack-9.4.yaml.lock b/stack/stack-9.4.yaml.lock
new file mode 100644
index 00000000..f60e5578
--- /dev/null
+++ b/stack/stack-9.4.yaml.lock
@@ -0,0 +1,19 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages:
+- completed:
+    hackage: Chart-cairo-1.9.3@sha256:5d6f005b5d3d74453a979eb2c6a1777c92ce02eae9e019abbe03a0e008cb8aea,924
+    pantry-tree:
+      sha256: 204f29235d182cc8c8ab40d0a37387e78c1dadc684e190c85e1643521483e681
+      size: 238
+  original:
+    hackage: Chart-cairo-1.9.3
+snapshots:
+- completed:
+    sha256: 7d4b649cf368f9076d8aa049aa44efe58950971d105892734e9957b2a26a2186
+    size: 640060
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/21.yaml
+  original: lts-21.21
diff --git a/stack/stack-9.6.yaml b/stack/stack-9.6.yaml
new file mode 100644
index 00000000..112e3598
--- /dev/null
+++ b/stack/stack-9.6.yaml
@@ -0,0 +1,55 @@
+resolver: nightly-2023-11-23 # GHC 9.6.3
+
+packages:
+- ..
+- ../ipython-kernel
+- ../ghc-parser
+- ../ihaskell-display/ihaskell-aeson
+- ../ihaskell-display/ihaskell-blaze
+- ../ihaskell-display/ihaskell-charts
+- ../ihaskell-display/ihaskell-diagrams
+- ../ihaskell-display/ihaskell-gnuplot
+- ../ihaskell-display/ihaskell-graphviz
+- ../ihaskell-display/ihaskell-hatex
+- ../ihaskell-display/ihaskell-juicypixels
+- ../ihaskell-display/ihaskell-magic
+- ../ihaskell-display/ihaskell-plot
+# - ../ihaskell-display/ihaskell-static-canvas
+- ../ihaskell-display/ihaskell-widgets
+
+ghc-options:
+  # Eventually we want "$locals": -Wall -Wpartial-fields -Werror
+  # ghc-parser: -Wall -Wpartial-fields -Werror
+  # ihaskell: -Wall -Wpartial-fields -Werror
+  # ihaskell-widgets: -Wall -Wpartial-fields -Werror
+
+extra-deps:
+# https://github.com/amcphail/plot/pull/23
+- git: https://github.com/codedownio/haskell-plot.git
+  commit: dfa26022b5815bcd6a5dd6c818fcd2c4d25c6d44
+
+allow-newer: true
+
+nix:
+  packages:
+  - blas
+  - cairo
+  - expat
+  - file
+  - fribidi
+  - gcc
+  - gfortran.cc.lib
+  - libdatrie
+  - liblapack
+  - libselinux
+  - libsepol
+  - libthai
+  - ncurses
+  - pango
+  - pcre
+  - pcre2.dev
+  - pkg-config
+  - util-linux.dev
+  - xorg.libXdmcp
+  - zeromq
+  - zlib
diff --git a/stack/stack-9.6.yaml.lock b/stack/stack-9.6.yaml.lock
new file mode 100644
index 00000000..c2900274
--- /dev/null
+++ b/stack/stack-9.6.yaml.lock
@@ -0,0 +1,23 @@
+# This file was autogenerated by Stack.
+# You should not edit this file by hand.
+# For more information, please see the documentation at:
+#   https://docs.haskellstack.org/en/stable/lock_files
+
+packages:
+- completed:
+    commit: dfa26022b5815bcd6a5dd6c818fcd2c4d25c6d44
+    git: https://github.com/codedownio/haskell-plot.git
+    name: plot
+    pantry-tree:
+      sha256: f79914b2d62db05a5aa7e1c36ef5fc887270582255172433449ef252aa1d1057
+      size: 2855
+    version: 0.2.3.11
+  original:
+    commit: dfa26022b5815bcd6a5dd6c818fcd2c4d25c6d44
+    git: https://github.com/codedownio/haskell-plot.git
+snapshots:
+- completed:
+    sha256: 3a1d76b27b77ecf9541ee3723756ff85d7bca58340a6858e760a1d7ef4d055bd
+    size: 698983
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2023/11/23.yaml
+  original: nightly-2023-11-23