JS GHC Backend, Hascalators, Transpilers, and Javascripters in Haskellland

So I’m glad that there’s now an official JS GHC backend, but after getting lambasted on not knowing the difference between compilers and transpilers on IRC, I do have to vent my pique here.

I confess that, through my ignorance, I’m at fault, but the JS GHC backend is not human readable and comes with the full Haskell RTS. This is a big problem because, well, from what I’ve seen of certain JSers and Haskellers, JS is potentially a new Hascalator (wherein Scala users keep getting fed up with the limitations of Scala and jump ship to Haskell). It seems many advanced Javascript developers are into functional programming, attempt to import Haskell-style features into JS (see the notorious FantasyLand incident), and some have even gone so far as to say “to get JS, you should learn Haskell first”. And while you might know of certain prominent Haskellers who were working in Javascript before they got their Haskell jobs, I’m shocked by what seems to be an abnormal number of Javascript developers who decided to learn Haskell.

The fact that the JS GHC backend is a compiler, not a transpiler, is disappointing in that we can’t cater more to the needs of Haskell’s JS fans. Human-readable, or at least JS-recoverable, transpiled Haskell code has the advantage that if a shop already working in functional Javascript wants to do Haskell as an experiment, in case of failure, they can always transpile back into JS and recover their efforts via Node or whatnot, encouraging at least experimental Haskell use. Likewise, the ability to transpile out, means that for Haskellers, if our Haskell code is impenetrable to people unused to expression-oriented languages or the various abstractions Haskell uses, we can always dump into an extremely-commonly-used language to make our code useful.

Of course, it’s unreasonable to expect the JS GHC backend to be anything else; Fay already exists, but is intended to be a subset, Purescript already exists, but is strict, Elm is already there, and lacks typeclasses, or, JS GHC differentiates itself by attempting to translate as much of Haskell as possible (TH isn’t expected on the first pass).

But are there any serious efforts to either fully transpile Haskell into JS, or alternately at least present a human-readable Haskell code in JS? Performance is not the emphasis, the emphasis is being able to show our <$>, >>=, $, infested, IO-monaded code to passerby or otherwise present recoverable code after a failed project.

It’d also help with Javascript learners of Haskell; i.e, if they can’t get their project working, well, they already know the “assembly of the web” (not to be confused with WASM, of course), they can compile, then hack away at the resulting code, and still have a usable project.

Come to think of it, I don’t see anyone else noticing the JS-to-HS train, am I misinterpreting the evidence? If not, are there any efforts to help these folks along and hopefully move Node / JS shops into Haskell or Elm-Haskell shops?

I’m sorry people gave you crap on IRC. :frowning: Sounds like people dying on the hill of minute definitional differences.

The thing about Haskell is that it isn’t just a nice syntax. The runtime is responsible for a lot of optimization and behind-the-scenes organization that enables the nice syntax. It raises the abstraction layer. I can’t imagine that any performant implementation of the runtime will ever trans/compile into something that would catch the eye of newcomers.

But does it need to? As you note, there are already things like Fay and Elm.

Furthermore, rather than introducing people to Haskell by explaining how Haskell is implemented, it might be better to focus on making it easy to try out, or figuring out how it can conveniently solve problems they have.

9 Likes

Firstly, sorry you had a bad IRC experience :frowning: I hope you don’t feel that way here!


The fact that the JS GHC backend is a compiler, not a transpiler, is disappointing in that we can’t cater more to the needs of Haskell’s JS fans.

I think this is what I disagree with. For me, running Haskell on the web is a killer feature and being able to FFI to the vast JS ecosystem is so powerful it’s incredible. I don’t know how I could be disappointed that something this powerful is in the ecosystem.

I would be very excited, separately, in a transpiler because of the value it could provide, but I don’t think the two tools actually compete that much: compiler is for Haskeller’s who want to run on web and FFI into JS; transpiler is for people who want to write in Haskell and then use the JS, which is harder to do with a compiler.


I’m skeptical of using transpiled JS from Haskell. Haskell has a lot of complicated details that will be very confusing in a transpiled version. For example: sum types; type erasure; newtype value erasure; class dictionaries will be passed around manually, which could look really weird.

Not to mention the biggest one: Haskell is lazy, and the JS code would be incredibly confusing to look at with the sever number of closures being generated and called…


If the JS-to-Haskell train is real, isn’t a good solution to have a good way to export definitions from a GHC-JS. Doesn’t that cover most of the use cases, such as “oh look, I have this mini-DSL that I want to work with in Haskell; I’ll write that in Haskell and FFI from JS!”

3 Likes

What’s your sense of how hard it would be (in a near future where there’s an easy to use GHC javascript backend) to use a library like say Plotly javascript graphing library in JavaScript within a Haskell application?

More generally, do you have thoughts on the kinds of applications in Haskell that this GHC backend might make feasible? I’m just curious to get a sense of the possibilities.

I’m more oriented toward the industrial use-case; i.e, a Haskell-JS transpile that produces refactorable JS code allows project managers to go: “if our Haskell experiment fails, we can always transpile to JS and just do it via Node instead”.

If you’ve read Stephen Diehl’s comments on Haskell marketing, the risk assessment is a big part of language choice. Java might be ugly and expensive, but project managers have a clear idea of the costs and risks, whereas Haskell doesn’t. Providing a Node.js fallback if a Haskell project fails (can’t get enough developers, Haskell devs have insufficient skill, etc) substantially mitigates the risk of Haskell for JS shops and encourages them to adopt Haskell, as Juspay.in did:

I guess what I’m pushing for is to figure out a way to make the JS backend of Haskell usable for JS-only developers to recycle failed Haskell projects. I.e, have modes that generate less unreadable code, even at the cost of performance, encouraging project managers to just go “f- it, let’s go with Haskell, we transpile to usable code for Node.js if this goes bad”.

===

Overall, if you look at Clojure, one of their biggest advantages is that they run on JVM and therefore can utilize all Java libraries. But moving Haskell to be optionally on Node.js and npm is even more powerful than running on JVM; the ecosystem we’re hijacking is absurdly massive, and we already are sort of Javascript’s “type-level programming / template C++” level of high coder skill.

And between JS and Python, Python is quite resistant to cannibalization as Python rarely scales to the extent where Haskell type-safety matters, and Python is already comparably terse to Haskell, winning out when it comes to gluecode syntax. Luckily, it seems JS still has more developers than Python.

That makes sense! I guess the reason nobody is working on it is simply time constraints or lack of interest. You could be the one. :slight_smile:

I know the people working on the JS and WASM backends are still focused on correctness and performance right now. They are committed to using Haskell on JS runtimes so don’t need an escape hatch.

2 Likes

I am guessing this niche of people is captured by either fp-ts or rust currently…You see regular mentions in the ReScript forums of people saying the “transpiling is so nice, why not emphasize node/backend more?”… I personally would bet on rust this year or just use plain Haskell (with a prolific library developer on staff) if I wanted a better node that was palatable to managers. I think many haskell shops look at the lack of libraries and just brute force their way through the problem and build just enough libraries to serve their needs.

But (as noted by @santiweight) transpiling from e.g. Rust to JS will always be easier than transpiling from Haskell - Rust and JS are both strict/eager languages (anyone for a nonstrict/lazy JS?)