83 comments

[ 3.4 ms ] story [ 176 ms ] thread
Very cool! However, could they not compile the Haskell Elm compiler to JS using GHCJS and then write Elm bindings for it?
One of their stated goals is to show people how to write a compiler in Elm, and another is to allow programmers familiar with Elm to hack on the Elm compiler without needing to learn Haskell.
The compiler written in Haskell relies on some extensions and/or optimisation tricks that make it not possible to compile with GHCJS. The 0.18 compiler (or maybe it was 0.17) was compiled with it though, it was what Ellie (third-party online playground) used.
One thing to note is that writing the compiler in Elm instead of just compiling the Haskell compiler to JS allows us to expose bits of the compiler as an Elm library.

I mean, being able to bootstrap is nice and nerdy and so on, but I believe exposing the parser, optimizer, type inference etc. as standalone functions will be the most impactful aspect of the repo, in terms of enabling better tooling in the Elm ecosystem.

Sad that they have to put a massive "Non-goals" full of emojis so the main Elm team does't feel threated. A languange doesn't lose anything with an extra compiler - a competing compiler is actually what Elm needs right now.
I don't see how the emojis have anything to do with that section, since they're all over the readme anyway. Aside from that: what they're stating is that they "don't want to and aren't planning to divide the community into multiple Elm derivatives, and will actively try to prevent that". Not dividing the community is not the same thing as threatening the main Elm team. And for a smallish language like Elm it makes sense to me that they want to keep everyone on the same team.
To give a bit context, Elm main team has been defensive against forks. They are preventing development of features they don’t think worth to them. It’s not possible to publish packages with low-level access without Elm main team approval. The compiler even has built-in DRM about that. My point is more compilers is exactly what Elm needs to flourish. C has several compilers. Python has even”jython”. That doesn’t make a language community weaker.
We may live to see the day, hopefully, (a long time ago in a galaxy far, far away) where language designers join the 1970's and learn about open standards.

Their mind will be blown, probably.

(comment deleted)
> It’s not possible to publish packages with low-level access without Elm main team approval. The compiler even has built-in DRM about that.

Not calling you out or anything, but could you give a reference on that? I'm curious about what they're doing with a "DRM" in the compiler.

(comment deleted)
(comment deleted)
> Not calling you out or anything, but could you give a reference on that? I'm curious about what they're doing with a "DRM" in the compiler.

Check tester89 link - it’s the description about the state of Elm right now. Author’s experience matches my personal one.

This[0] is actually a better reference; the official post by Elm's creator on how accessing "native" code used to work, and how it now works.

Essentially, the compiler only allows packages published by two official Elm Github organizations to include native code. I'm not sure what the process is if a key "native" feature is missing, as this limitation also drove me away from the language.

[0] https://discourse.elm-lang.org/t/native-code-in-0-19/826

> Elm main team has been defensive against forks

What does that mean?

I know they have a strict vision of what features are better left out, and in a way I wish more langs'd be vocal about that. Go does the same and they seem to get a lot of praise for it.

Just like in Go, the Elm team only allows some features to be used by their own (std-) libraries. This, again, is a design choice.

No group was hurt enough to "fork" Elm. PureScript can be seen as a close relative that is less restrictive.

Go is open to forks and PRs though. It’s more “we’ve got a vision, but we’ll hear you out”. Elm is full cathedral, Elm comes down from the gods with no input or transparency into the decision process.

The Elm developers have a history of ostracizing people who even mention the possibility of forks from the community; tester89 posted a link with a lot of good context.

They take a very heavy handed and adversarial stance to development. I had just started getting into Elm when the news of .19 basically breaking everything and the core team just brushing off peoples cries and it soured me on the entire language.

When pre-v1 Go broke things, `go fix` was there to at least try and help.

There was a similar project to `go fix` with elm-upgrade (https://github.com/avh4/elm-upgrade). We migrated a ~100k LOC app at work from 0.18 to 0.19 and while it was tedious, the compiler really has your back and makes it easier.

We weren't bit by the removal of native/kernel code, but it definitely turned a lot of people away that may have been committed to Elm before.

True that.

We also ported our Elm codebase from 0.18 to 0.19. It took us almost a week working almost 24/7 across two timezones to make the damn thing compile again. Did not see the UI for the entire week, but once it compiled it (mostly) just worked like nothing had changed (that's after 429 files changed, 16422 insertions(+), 12116 deletions(-)).

My colleague took notes of the progress at https://gist.github.com/mordrax/efcd34739ed56bb64d2b12d2401b...

Wow! Apologies if this is answered in those notes but my quick question is: Did you make extensive use of Debug.todo to cordon off sections of the app that wouldn't compile in order to work on and "see" the other sections in the meantime? That's what I do on my small elm apps, e.g. put whole features or functionality behind Debug.todos.
I might be wrong but I think Debug.todo was introduced in Elm 0.19. But in any case we were not aware of it at the time and didn’t use it. Btw Debug.todo is amazing and we do use it now sometimes.
From the gist:

> We have until Friday 7th September to upgrade to Elm 0.19.

I'm completely ignorant about the transition, but I'm curious what the source of this deadline was. Would you mind expanding?

Basically business didn’t see any benefits of spending time on the upgrade, time that could be used to improve/add features to the product.
I remember hearing Mordrax speak about the upgrade, quite herculean!

At our company it was much less drastic. At the time we had about 35kloc of Elm and it took me one evening of Vim macro frenzy. The trickiest things we encountered were an elm/http API change and temporarily vendoring packages that didn't yet upgrade themselves.

Sounds like Go's cathedral has a nice little bazaar in front, once a year, only for those who applied and were grated. In other words: better marketing.

I'm not defending Elm team members being rude. But when I look at Elm I see a much better designed language than Go, run by a much smaller team. Elm changes quite minor things in pre-1.0. Go forgot that polymorphism is cool, nulls are bad, etc. Now Go wants to fix some of that, but that would create a new notion of idiomatic Go that it's std lib is not in sync with.

To some extend this is a fate all popular languages befall. Look at Java for some sci-fi, or even better C++.

> basically breaking everything

This is unnecessarily dramatic, and far from the truth.

> Elm main team has been defensive against forks

You're more than welcome to create a fork, as long as you name it something else. This is so people are not confused as to what they are getting into! :)

I like it! I gather now you can compile Elm in the browser? It allows many things, similarly as F# with Fable, which allows to compile F# code in browser without a server.

Ability to compile code in browser allows to do sandboxes, or tools that otherwise would require a server.

I think the project is a while off of being properly usable. I think it's mostly written with Node in mind, but shouldn't be too difficult to swap out the Fs bits for browser-specific code.
As pd-andy says, it's not finished yet, but yes you're right, that's one of the things it will enable: interpreting Elm code from within Elm - an eval function of sorts.
Serious question: how popular is Elm? I've recently seen some tutorials showing up and anecdotally know some friends that have played around with it, but I haven't seen any job postings for it and so I'm wondering if it's just hyped up or if there is real demand for Elm developers professionally.
I write Elm full time, so there are definitely jobs out there.

That said, I suspect that given how fun the language is to write, supply probably outpaces demand a bit. Which is actually good, in the sense that for many companies adopting a somewhat less mainstream language one of the main concerns is "will I be able to hire for this?", which generally the answer is "yes, especially for more senior positions".

Neither, really. I'd say it has the largest community out of the various compile-to-js statically typed FP langs, at least with an explicit front-end focus.

- PureScript has a small but passionate community, one of the biggest players in that community laid off their whole ps team so that doesn't bode well.

- ReasonML fractured into ReScript but left half the Reason community behind, it's a confusing space to navigate now.

- GHCJS...

Most (perhaps even all) of the job postings end up on the elm slack (rather than, say, reddit or other more visible places).

There was some controversy with the release of 0.19 a couple of years ago, and general contempt (in the wider community, not inside Elm) for the way the language is developed and run which means there isn't a great deal of buzz about it outside of those already using it.

If you don't have the urge to jump off a hill when you see heavy pragmatism, Typescript is very popular and well maintained. My experience is only positive.

I was also wondering, does Blazor work with F#? That could also be an option. Not a front-end focused language but a front-end focused framework, so, there's that.

I truly believe TypeScript is the only true way forward for frontend web programming.

Now what we really need is a functional dialect which compiles to TypeScript...

> Now what we really need is a functional dialect which compiles to TypeScript...

Why would it be beneficial to have TS as an intermediate representation? It turns into JS anyway, and there are already statically typed functional languages that compile to JS.

It would massively simplify the job of proving the upper language more correct. It may also be possible to proxy the type system in order to make use of existing tooling.
TypeScript has a bunch of holes in it because it needs tight compatibility with JavaScript. While a pure functional style may be possible, it isn’t first-class or ergonomic or as expressive, and won't cut it for many. Are there first-class function composition infix operators? Is pattern matching algebraic data types often the easiest way to write code? Is IO managed? With a language like Elm and others in the ML family, functional style is the only game in town, not just the in-house convention, and it's easier to have people using a similar style if it’s ergonomic. Even if you’re willing to give up managed IO OCaml and Reason are going to suit this programmer better than TypeScript. I would not be surprised if a lot of the fp-ts crowd is merely tolerating this as a comprise.
I didn't say we should use Typescript, I was suggesting a FP dialect which compiles to typescript.
TypeScript or Flow for that matter sucks at using functional style with immutable data types. There are ESLint plugins that allows to enforce immutability with plain JS objects, but still lack of syntactic sugar or union types makes the experience much worse then in functional languages.
https://github.com/tc39/proposal-record-tuple

Only stage 2, so whether it'll get through to next stage is up in the air, will depend on interest (compare to Temporal which started fairly slow but has gained huge momentum recently and is now at stage 3 and engine testing level) but it's encouraging.

Perhaps what we need is a dialect which compiles to typescript and supports (or better, enforces) the immutability you suggest.
Oh yeah I knew I was forgetting one, F#/Fable seems really popular among F# devs, but it doesn't seem like it's picking up any traction for FE devs that aren't already in that community.

Typescript encourages and is generally more conducive to a different style of programming. That's OK (in fact, clearly it's more than OK given its popularity) but it's not really the sort of thing I want to be writing. I think it's worse if you commit to something like fp-ts or the fantasyland stuff, personally.

> PureScript has a small but passionate community, one of the biggest players in that community laid off their whole ps team so that doesn't bode well.

I wouldn’t let that dissuade anyone. Even if support diminishes, the language is feature complete, and FFI is so stupidly easy you can freely co-opt JS libs as needed.

There is also clojurescript which is fairly popular. I am not a large fan of using these for websites since they have their own heavy runtime that needs to be shipped. ReasonML did fairly well in this aspect but there is still a baggage.
There was a sizable rift after Elm’s 0.19 version. Removing synchronous FFI, especially to existing browser APIs that haven’t been rewrapped with a new API by the core team caused a lot of individuals and businesses to migrate mainly to PureScript, Reason, and/or Typescript—myself included. Couple with community hierarchy issues, lack of development/roadmap transparency, rotting merge requests to the core libraries (security, bugfix, and performance issues), and community libraries, Git hosting, and identity tied solely to Microsoft’s GitHub accounts, it’s not something I personally could recommend. I do however think it’s a great learning language—especially for first-time functional programming—but I would be very hesitant in your assessment for production if you need to scale to use browser APIs, i18n, l10n, etc. or like/need the ability to fork and contribute to the core.
I've been a fan of mint-lang; although it's early, it's clearly intended to be like Elm: The Good Parts. Also fearing a small but helpful community that welcomes contributions, which is the polar opposite of my experience with Elm.
I’ve been writing Elm professionally for the past 2.5 years on a large project. The language is a pure joy to use, unparalleled refactoring experience. Yes it’s a small community, but there’s many jobs posted on Elm slack.
It’s quite parallel to typescript (strict) refactoring, isn’t it?
I suspect not. With Typescript even with strict typing, mutating state is still possible (I believe, correct me if I'm wrong..). This adds an extra layer of complexity to the refactoring process.

With Elm, mutation is impossible - everything goes through the update loop. There are no escape hatches. This does mean you have to jump through a number of hoops to use FFI. It can be a pain at times, but does make for much easier refactoring.

> This does mean you have to jump through a number of hoops to use FFI.

TBH, I thought the pain of FFI in ports (the only mechanism available in Elm 0.19) was kinda overblown. Function input goes into a command, function output comes back as a message. That's just a few extra lines of standard code.

I think they become annoying if you do lots of small, synchronous, safe calls, like using a JS math library. In that case I suspect I would prefer writing a larger JS function instead of having an Elm function full of JS calls, even if I could use a more permissive unsafe FFI, because every JS invocation is still a chance at runtime errors due to type conversions (even with ports).

(comment deleted)
Honestly, it's nothing alike. Refactoring in Elm is different, as the compiler will tell you if you did the correct thing when refactoring. The typescript compiler can only do a fraction of that, even if you type your stuff correctly.

Needing to type stuff in elm is mostly optional too. The compiler will still check it for you anyway.

There where an article recently regarding Humios use of Elm: https://www.humio.com/whats-new/blog/why-we-chose-elm-for-hu...

Using job postings isn't really that useful. If they where any indication then the two only language in existence would be Java and C#. That depends on where you live of cause. E.g. there are plenty of Python jobs around where I live, but they aren't frequently posted on the regular job sites. I'd suspect that Elm jobs are posted where Elm developers are to be found.

The #jobs section on the Elm Slack is quite alive.

Can't speak for the community as whole, but there is at least some demand: the company I'm working for is actively hiring Elm devs for at least two teams at this moment :)

I write Elm and I hire Elm (and Haskell) programmers. It works great for our business so we’re going to continue doing that.
We have a team at Square that uses Elm and I've made a few commits. They've been working on their app for around 18 months now.

I find it slightly funny because I also write Svelte at work and that app is public facing so it gets public attention but the Elm app is internal facing so the public will never see it. Also helps that Svelte uses its own name in the code it generates. Which is why I try to promote Elm myself. To semi-quote @SvelteSociety "@Square, a >$100 billon company, uses @elmlang."

Hello! Author here. Didn't expect to land on HN before the compiler is actually useful - Oto, you'll pay for this! :)

Feel free to ask me anything about the project, although bear with me - I'm learning compilers/... on the go, didn't study them or anything.

I know you're not trying to replace the official Elm compiler, but that's precisely what is needed. I really, really wanted to like Elm but the way it's managed is horrible and antithetical to the idea of Open Source software. With the current compiler I wouldn't touch Elm with a 39.5" pole, even if Elm is a joy to work with.
One's attitude towards Elm directly correlates with the degree to which one likes to dig into and tinker with the internals of their tools and frameworks and rearrange things. Unfortunately that means it's a hard sell around HN-- in a way it's antithetical to "hackers". But I don't think it's antithetical to John Carmack's proverbial "engineer"-- someone who wants to do what they can do with what they've actually got. Elm lets me do what I want to do, exceedingly efficiently and makes it fun, and that should make it a good choice for plenty of projects.
I don't buy this argument.

I am also someone who just wants to get shit done. I've never had an issue with php, c#, ruby, crystal, go, rust, haskell, erlang etc's compilers/interpreters in terms of letting me get what I want done. Yeah, I haven't actually forked or patched those compilers but neither have they been hostile to their users.

The reason I would use literally any of those except Elm is that the maintainer(s) of Elm act like they're Steve Jobs. How can I "get things done" if I'm being told "oh no, you're not allowed to do <standard-thing-X>, we've decided that only us on the Elm team can do that". With other languages, I'm not worried about a version bump pulling the rug out under me, effectively trapping me in the ecosystem unless I want to rewrite everything in a different language. That is also directly the opposite of being productive and getting things done.

There is nothing about an autocratic "you're holding the compiler wrong" governance model that makes any part of a language itself more efficient or fun. Plenty of other languages are as (or more) efficient and fun as Elm, but without the patronizing and condescending attitude of "you're not as smart as us, so do as you're told, and no you can't discuss this with us". There is no way I could justify the risk of adopting elm professionally given the entire rest of the programming language world... doesn't do this. Let me be the one who decides to shoot my own foot off; even Rust (a language pitched on memory safety) allows this with unsafe, etc.

If one wants to control everything exactly and go against almost every other language and most F/OSS projects, then just... make proprietary/source-available software. F/OSS is a give-and-take, and nearly all of us have taken far more than we've given.

And I don't know what John Carmack's "proverbial engineer" is, but I think just about any engineer would prefer to be in control of their tooling and not at the whims of maintainers.

> How can I "get things done" if I'm being told "oh no, you're not allowed to do <standard-thing-X>, we've decided that only us on the Elm team can do that".

I think this is common in almost any language. For example, in JavaScript there isn’t a way to turn off the garbage collector. Why are browser authors limiting us? I’m sure they have good reasons - reasons that I may not fully understand but that’s fine! Maybe this isn’t the best example but I’m sure you or someone else could think of one for me.

Anecdotally, even when lower level/advanced features are exposed, I personally haven’t had the need to reach. For example, say python allowed for custom memory management features - I’ve never had the need for them! And I’m just fine working on a large django application with thousands of concurrent users. This isn’t to say I will never need some advanced lower level feature of python, however, I haven’t needed for >5 years.

The point is, if elms feature set works well for most of its applications - what’s the problem? The creators have a vision for the constraints of the language! Which is directly related to the intended goals and benefits of the language

I really would love to have this compiler have a llvm backend. I like the idea of a small FP language with amazing error messages. Haskell is too big and complex for me.
I've briefly looked at LLVM and how to interface with it but back then I didn't find much else than some C++ Builder API. I'd hope for some textual format that I could give to LLVM as an input. I assume it exists and that I've just been googling wrong :) Would definitely appreciate some pointers in that regard.

Other than that my best bet for native binaries is most likely compiling to C or GraalVM (which already exists as an experimental backend in elm-in-elm via Truffle!)

The textual representation is known as the LLVM IR (the reference is at https://llvm.org/docs/LangRef.html). My understanding (as purely an amateur enthusiast) is that generally using a higher-level builder, like the ones for C++ or OCaml, is recommended, but that it's entirely possible to generate the IR directly.
As the other comment says, LLVM has a text based IR. But you may also want to look into QBE which is simpler and lighter weight than LLVM but has a similar text interface so you could start with that to get up and running, and then add support for llvm later.
Compiling down to C is a great idea as well. Nim does that
AFAIK Elm can't actually write to the filesystem, how does the compiler get around that? Or has Elm changed such that it can work outside the browser now?
I use ports to write to the filesystem. There is a small amount of JS that initializes Elm, which runs in Node and has the ability to write to the filesystem.

Of course if you'll be running elm-in-elm in the browser, you won't be able to do that. But there are more interesting things to do with a compiler in the browser :)

eie.io would be an awesome domain name for this project. Too bad it's already parked by a squatter as a "premium name". (For non-native or non-Western English speakers, it's a line from the children's song "Old McDonald Had a Farm".)
Premium names aren't squatted but designated as such by the central registry. For the TLDs .ac, .io, and .sh those are previously unavailable short domains that are now released to public and auctioned by Divido, the company that has set up the site you see.
> EIEIO (“Enhanced Implementation of Emacs Interpreted Objects”) provides an Object Oriented layer for Emacs Lisp, following the basic concepts of the Common Lisp Object System (CLOS). It provides a framework for writing object-oriented applications in Emacs.

https://www.gnu.org/software/emacs/manual/html_node/eieio/

Also relevant to compilers, it's a fence instruction in PowerPC:

> eieio (Enforce In-Order Execution of I/O) instruction

> Ensures that cache-inhibited storage accesses are performed in main memory in the order specified by the program.

Great work, Martin! Excited to see how the project turns out <3