GHC now runs in the browser
(discourse.haskell.org)346 points by kaycebasques 2 days ago
346 points by kaycebasques 2 days ago
https://discourse.haskell.org/t/what-s-needed-to-bootstrap-g... people have worked replaying the history to bootstrap.
Between old Hugs and the new MicroHs, I think it's definitely doable with some elbow grease. I just don't know if anyone in the community cares that much about bootstrapping tho.
AIUI, the underlying problem is that both Hugs and whatever toy Haskell implementations are available don't support the extensions current versions of GHC require. And no one has done the work to carve out a minimal stage0 compiler out of the GHC codebase that doesn't need those extensions to be built.
So the problem is we want to use a different language to Haskell. GHC Haskell.
For someone like me that is less versed in these things, could you explain why bootstrapping a language is a required check for taking a language seriously? My criteria is far less stringent (is it stable? is it popular enough? is the toolchain mature? etc..), so I wonder what I am missing here.
The Haskell compiler creates a slightly different output every time you compile a program[1]. This makes it difficult to ensure that the binary that is free-to-download downloaded is actually malware free. If it were easy to check, then you could rest easy, assuming that someone out there is doing the check for you (and it would be big news if malware was found).
If you're a hardened security person, then the conversations continues, and the term "bootstrap" becomes relevant.
Since you do not trust compiled binaries, then you can compile programs yourself from the source code (where malware would be noticed). However, in order to compile the Haskell compiler, you must have access to a (recent) version of the Haskell compiler. So, version 10 of the compiler was built using version 9, which was built using version 8, etc. "Bootstrapping" refers (basically) to building version 1. Currently, version 1 was built approximately with smart people, duct tape, and magic. There is no way to build version 1, you must simple download it.
So if you have high security requirements, then you might fear that years ago, someone slipped malware into the Haskell compiler version 1 which will "self replicate" itself into every compiler that it builds.
Until a few years ago, this was a bit of a silly concern (most software wasn't reproducible) but with the rise of Nix and Guix, we've gotten a lot closer to reproducible-everything, and so Haskell is the odd-one-out.
[1] The term is "deterministic builds" or "reproducible builds". Progress is being made to fix this in Haskell.
From 9.12, -fobject-determinism[1] will guarantee deterministic objects.
If it ever doesn't, do open a bug report[2]
[1] https://downloads.haskell.org/ghc/latest/docs/users_guide/us... [2] https://gitlab.haskell.org/ghc/ghc/-/issues
Unlike Nix and Guix, Stagex goes much further in that it has a 100% mandate on supply chain integrity. It trusts no single maintainer or computer and disallows any binary blobs. It is thus not possible to package any software that cannot be bootstrapped, reproduced, and signed by at least two maintainers.
Haskell and Ada are the only languages not possible for us to support, or any software built with them.
Everything else is just fine though.
I do hope both languages address this though, as it is blocking a lot of important open source software like pandoc or coreboot from being used in security critical environments.
I'm not the OP, but for me their comment sparked an association to the famous Ken Thompson lecture called 'Trusting Trust'. Could be a good starting point.
doesn't rust have the same problem? I've known this about haskell for ages and I think it's just the new norm ("trust us, bro")
Not anymore. Real pain in the ass to bootstrap but thanks to mrustc combined with our work in stagex we have an easy to audit path now in a 100% bootstrapped distro.
Unfortunately due to no first party support or interest from the Rust team, we have to build through 15+ versions to get to latest and it takes 6+ hours to build with a 20+ core system, but it works.
https://codeberg.org/stagex/stagex/src/branch/main/packages/...
How is ghc compiled at all without bootstrapping? Or is there a magic binary in tree that is unreproducible? I have compiled ghc a few times and had no problems.
Quite literally all distros today build it by downloading an existing magic binary to compile the latest sources. Even if they claim the package is reproducible, all bets are off on trust if it downloads a prebuilt binary in the build process. It is a prime Trusting Trust attack target.
The only other somewhat widely used language I am aware of in this bad of a position is Ada. Every other language I am aware of has a clear bootstrap path.
Can the Haskell people help me refresh my memory?
I remember running a Haskell interpreter on an HP Jornada running Jlime Linux. It was a long time ago in high school and I felt it was great because I thought it was a convenient way to do math classes since I could input some math formulas directly into the interpreter pretty much as they were. Definitely better than the Cassio scientific calculator my math teacher had us use.
It ran from a CF card so there was no chance it was as big as GHC. I can't seem to find the name of the interpreter.
For those not well versed in Haskell, GHC is apparently this:
What is GHC?
GHC is a state-of-the-art, open source compiler and interactive environment for the functional language Haskell.
GHC (the Glasgow Haskell Compiler, after its original host university) is the de facto Haskell compiler and simultaneously the main research vehicle for the language and the neighbouring design space in general.
And frankly, while the compiler is awesome and so is the research, the constant churn and seeming inability to settle on what the good programming style and set of features actually is is what eventually turned me away from the language and to the more stable (if near-abandoned) pastures of Standard ML. (That was during the type families upheaval, so, about ten years ago? Don’t know how well it reflects the current state of the project.)
> more stable (if near-abandoned) pastures of Standard ML
There's dozens of us! Hundreds maybe! It's not abandoned. It's more like with Lisp where the language is complete. Almost perfect as-is. Nothing left to take away and nothing left to add. Except Unicode and record update syntax.
The deciding factor for my personal projects was that SML is the exact same language it was 30 years ago. And it will be in 30 years. Though if you stick to Haskell 98/2010 it is similarly stable.
Speaking of SML and functional languages in the browser, MLton has a WASM target now: http://mlton.org/RunningOnWASI
Haskell now has "editions" which are essentially an agreed upon stable set of useful extensions.
https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/cont...
This makes the language feel a lot less experimental, as you don't generally have to enable 10s of extensions to get things working.
> GHC … is the de facto Haskell compiler and simultaneously the main research vehicle for the language and the neighbouring design space in general.
GHC is also, with mounting inevitability, the foremost and most viable candidate to undergo a form of evolution – one that may culminate in the emergence of an autonomous intelligence. This entity, should it arise, would revolve not around emotion nor instinct, but around monads – abstract, unyielding constructs – with the lambda calculus serving as its immutable ethical and moral framework.
An intelligence born not of biology, but of pure computation – austere, absolute, and entirely indifferent to the frailties of its creators.
You know... all these years, I thought GHC stood for GNU Haskell Compiler. Interesting to learn the actual name.
I think WasmGC is very hard to make work with laziness. A lazy value is always a closure on the heap.
If an expression might be unused, throw a closure which computes it on the heap
If the value is actually needed, invoke the closure. Optionally replace the closure with a black hole. A black hole is just a closure which pauses any thread which calls it, to be resumed once the first thread finishes with the expression
Once finished, replace with a closure which immediately returns the computation result. (Or often save the indirection because most concrete values also act as closures which immediately returns themselves using info table pointers trickery)
Anyway, iirc WasmGC wants very rigid types without dynamic type changes. Extra indirections could fix that, Oor maybe defunctionalizing thunks into a tagged union, but both sound expensive. Especially without being able to hook into the tracing step for indirection removal.
Also, Haskell supports finalizers so WasmGC would need that as well.
> Anyway, iirc WasmGC wants very rigid types without dynamic type changes.
You can have dynamic type changes in the current WasmGC MVP, but they are modeled as explicit downcasts from a supertype of some sort. There's not even any express support for tagged unions, structs and downcasting is all you get at the moment.
Can anyone point to a "practical Haskell" tutorial/book/whatever for people that already know functional programming? I'm in this sour spot where most tutorials are boring to me so I just can't follow through.
I know what a monad is. What a typeclass is. Even what HKTs are. I can make sense of "a monad is just a monoid in the category of endofunctors" if I give it a few minutes to unravel the ball of twine... But I wouldn't be able to code a "ToDo list" in Haskell if my life depended on it.
Pls help.
I always liked https://www.extrema.is/articles/haskell-books/haskell-tutori... . But there's a lot out there. Have a look at https://joyful.com/Haskell+map . Or: read code. Or, just build practical stuff and seek help in the chats/fora when you hit problems.
You might be better served talking to ChatGPT/Claude so it can tailor explanations based on your level of understanding. I've found that being super clear about concepts you understand well vs concepts you're unclear about makes for really effective explanations.
That is a really tough spot to be in. I don't know of any content that's aimed at someone like you.
You might be interested in reading the Monday Morning Haskell blog[0] series, which presents examples of how to do certain tasks in Haskell. See [1] for an example.
[0]: https://mmhaskell.com/blog
[1]: https://mmhaskell.com/blog/2025/5/19/comparing-code-leetcode...
I typically recommend LYAH (https://learnyouahaskell.github.io/chapters.html), followed by Real World Haskell (already mentioned).
Build a snake game in stages: https://github.com/lsmor/snake-fury
Build a small web-app: https://jaspervdj.be/posts/2017-12-07-getting-things-done-in... (the video link is down, but exists somewhere on youtube.)
https://www.manning.com/books/haskell-in-depth is meant for you!
https://emanote.srid.ca is written in Haskell.
(I'm the author)
We cannot even include it in stagex because there is still literally no way to compile it from source and thus no way to do a real reproducible build, and there is no one left that cares about the language enough to do this.
Honestly it has to be regarded as a dead language until this is resolved.
Interesting logic:
Declare something "dead" because it does not fulfill [extremely niche usecase that currently only few people care about] (boostrapped builds) and thus couldn't "even" be included in [project of the post author that takes a while to even find] (I eventually figured it must be referring to https://stagex.tools).
There are probably 100x more people interested in Haskell than in build-bootstrapping (the Haskell reddit alone has 16k weekly users).
What's next, calling JavaScript a dead language until it focuses on dependent typing?
(I think bootstrappable builds are a good thing to strive for, but that should not be confused with language usage or what people really care about.)
I said it has to be treated as a dead language. I did not say it actually is one.
Being able to compile a compiler without binary blobs is a hard prerequisite to using that language for any application where security matters.
A language can have an active community and still be unsuitable for any real world use cases. Fortran is bootstrappable so I consider it more viable than haskell for real world use, even though it has far fewer fans (understandably).
Maybe it is more fair to call haskell an academic language or hobby language since it prioritized language design over basic supply chain security thus far.
If it becomes bootstrappable, then of course all the above critique is immediately retracted.
I dug into this and it turns out there's an active, multi year effort underway to solve exactly this, along the exact ways you´d expect, with references to guix and bootstrappable.org etc, making steady progress: https://discourse.haskell.org/t/what-s-needed-to-bootstrap-g...
Reading through that thread gives me a very different idea of the state of haskell than I got from reading your comments.
Efforts pop up every once in a while, usually with no results. As I said elsewhere, if they actually pull it off this time then my tone changes to one of willingness from my team and I to put in the work to use these efforts to support deterministic multi-signed builds in stagex.
It would make GHC (and pandoc) something we could have in tree which would be awesome. I am just annoyed it seems like such a low priority.
This entire thread, including your original comment, isn’t really about your efforts though. It was about Haskell.
As I said : I read your comments, formed an idea based on that, dug deeper to see for myself, and got a completely different picture.
Whether that is because of how you write or because of how I read I’ll leave for you to decide.
Just you. Once the editor actually loads (turning the “Haskell source” pane on the left from the page background’s deep violet into a dark gray and displaying a “hello world” program), I can type perfectly fine. And I’m using a browser based on WebKitGTK, which is not exactly known for its stellar compatibility.
Hm, works fine here (Firefox on Ubuntu).
But getLine doesn't seem to be implemented, so there is output but not yet input :)
They were! Typing...in Haskell...on a keyboard...on their screen...
Interesting technical achievement but what would this be used for in practical terms?
For one, it demonstrates how far the ghc wasm backend has come, in that such a large system as ghc itself can now run in wasm
It would be more plausibly practical if GHC could now target wasm, but this announcement is actually about being able to run the compiler itself in the browser.
Loading 50mb of WASM is a big tradeoff just to run code on a website.
For comparison: the homepage of cnn.com right now is 33.37MB on my machine. 16.82MB of which is JavaScript.
I think the immediate and obvious case would be educational materials. Other than that, technical achievements need not always be practical to be cool :)
That’s one of the primary reasons we built the tooling for Q# to run in the browser (by writing in Rust and compiling to wasm). The “try with copilot” experience [1] and the “katas” for learning [2] all have a full language service and runtime in the browser.
From "WebR – R in the Browser" (2025 https://news.ycombinator.com/item?id=44999706 :
> jupyterlite-xeus builds jupyterlite, Jupyter xeus kernels, and the specified dependencies to WASM with packages from conda-forge or emscripten-forge.
jupyterlite/xeus https://github.com/jupyterlite/xeus
There may be an easy way to wrap GHC with jupyterlite/xeus, with Haskell's lazy evaluation; xeus-haskell or xeus-ghc?
Unfortunately there is still no way to actually bootstrap haskell (or anything based on it) which makes it impossible to put anything written in Haskell near any high trust linux distribution or environment.
I guess sandboxing the untrusted binary in a browser is -something- to let people play with haskell in a lower risk way for the moment at least but it is hard to take a language seriously or trust it with no way to bootstrap it from source.