# How to achieve anything like "cabal typecheck"

**URL:** <https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214>\
**Category:** Learn\
**Created:** [January 17, 2025, 1:50pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214 "2025-01-17T13:50:39Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![turion](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/turion/32/989_2.png) [@turion](https://discourse.haskell.org/u/turion)\
**Post date:** [January 17, 2025, 1:50pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/1 "2025-01-17T13:50:39Z")

</div>

In Rust, there is the immensely useful “cargo check” command, which typechecks the whole codebase. It just works. I expect any command like that to be even more useful in Haskell, since we use a lot of type level stuff in Haskell!

But I can’t seem to make it work for cabal in any nontrivial way. Sometimes you see a recommendation of `cabal build --ghc-options="-fno-code"`, and this may work for small, simple, single cabal packages. But it doesn’t work, it seems, already for cabal projects with more than one package. I doubt it would work for template haskell.

This seems like a huge omission in Haskell’s tooling landscape. Has anyone managed to fill in this gap, maybe with a hack? Or is there any work in progress towards something like this? I couldn’t find anything so far.

---

<div class="post-metadata">

**Author:** ![emlautarom1](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/emlautarom1/32/4080_2.png) [@emlautarom1](https://discourse.haskell.org/u/emlautarom1)\
**Post date:** [January 17, 2025, 2:17pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/2 "2025-01-17T14:17:28Z")

</div>

You could use something like [ghcid](https://github.com/ndmitchell/ghcid) which will automatically check the project on change.

Personally I prefer to use the language server for this kind of feedback loop.

---

<div class="post-metadata">

**Author:** ![turion](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/turion/32/989_2.png) [@turion](https://discourse.haskell.org/u/turion)\
**Post date:** [January 17, 2025, 4:39pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/3 "2025-01-17T16:39:00Z")

</div>

Can you easily include either ghcid or HLS into a script? For example, I’d really like to do something like `git rebase --exec "cabal typecheck` to make sure every commit typechecks. I don’t know of a way to do this with ghcid or HLS.

---

<div class="post-metadata">

**Author:** ![george.fst](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/george.fst/32/4933_2.png) [@george.fst](https://discourse.haskell.org/u/george.fst)\
**Post date:** [January 17, 2025, 5:13pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/4 "2025-01-17T17:13:18Z")

</div>

I hadn’t noticed this until now, but you’re right that `--ghc-options=-fno-code` appears not to work with `cabal build` (`/usr/bin/ar: dist-newstyle/build/x86_64-linux/ghc-9.10.1/hello-hs-0.1.0.0/build/Lib.o: No such file or directory`). But it does work with `cabal repl`, and indeed this is [utilised by `ghcid`](https://github.com/ndmitchell/ghcid/blob/b7dc5c4ee640b6c8137ecfd0a2b50df278015221/src/Ghcid.hs#L151). So, unless you’re interested in improving things upstream, you could hack something together by piping commands in to that.

---

<div class="post-metadata">

**Author:** ![george.fst](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/george.fst/32/4933_2.png) [@george.fst](https://discourse.haskell.org/u/george.fst)\
**Post date:** [January 17, 2025, 5:42pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/5 "2025-01-17T17:42:04Z")

</div>

Right, this is the best I’ve got (`--enable-multi-repl` and `all` are optional, but useful for multi-component projects):

```sh
echo ':set prompt-function \modules _ -> if all (== "Prelude") modules then System.Exit.exitFailure else System.Exit.exitSuccess' | cabal --enable-multi-repl repl all --ghc-options=-fno-code

```

---

<div class="post-metadata">

**Author:** ![TeofilC](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/teofilc/32/3987_2.png) [@TeofilC](https://discourse.haskell.org/u/TeofilC)\
**Post date:** [January 17, 2025, 6:22pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/6 "2025-01-17T18:22:24Z")

</div>

The options from [Interface Files with Core Definitions - Well-Typed: The Haskell Consultants](https://well-typed.com/blog/2023/02/interface-files-with-core/) might also be helpful for speeding this up with TH

---

<div class="post-metadata">

**Author:** ![Leary](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/leary/32/4348_2.png) [@Leary](https://discourse.haskell.org/u/Leary)\
**Post date:** [January 17, 2025, 7:11pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/7 "2025-01-17T19:11:06Z")

</div>

That `prompt-function` will `exitSuccess` when some modules have failed to load, so long as at least one loaded.

Another approach:

```sh
#! /usr/bin/env sh

check=$(
	echo ':q' | \
	cabal -O0 repl \
		--enable-multi-repl \
		--repl-options="-ignore-dot-ghci -fdiagnostics-as-json -fno-code" \
		2>&1 | \
	grep '"severity":"Error"'
)

if [-n "$check"]; then
	exit 1
fi

```

---

<div class="post-metadata">

**Author:** ![george.fst](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/george.fst/32/4933_2.png) [@george.fst](https://discourse.haskell.org/u/george.fst)\
**Post date:** [January 17, 2025, 7:37pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/8 "2025-01-17T19:37:17Z")

</div>

Ah, damn. I only tested it with a very simple project.

---

<div class="post-metadata">

**Author:** ![turion](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/turion/32/989_2.png) [@turion](https://discourse.haskell.org/u/turion)\
**Post date:** [January 20, 2025, 10:10am UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/9 "2025-01-20T10:10:07Z")

</div>

That sounds really promising, thank you very much! Unfortunately I’m stuck with GHC 8.6 and I can’t do --enable-multi-repl there it seems.

---

<div class="post-metadata">

**Author:** ![mpilgrem](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mpilgrem/32/2529_2.png) [@mpilgrem](https://discourse.haskell.org/u/mpilgrem)\
**Post date:** [July 16, 2026, 2:15pm UTC](https://discourse.haskell.org/t/how-to-achieve-anything-like-cabal-typecheck/11214/10 "2026-07-16T14:15:42Z")

</div>

Adding a link to a related 2013 issue in the Cabal project:

- [Explicitly support building with -fno-code · Issue #1176 · haskell/cabal · GitHub](https://github.com/haskell/cabal/issues/1176)
