80 comments

[ 3.3 ms ] story [ 35.5 ms ] thread
EDIT: Would like to see something similar with svelte.
I haven’t followed Elm very actively for quite awhile. My workplace has a kiosk product where I, along with two others, did the entire front-end UI in Elm. Multiple screens, a full configuration interface and talking to a C# back-end. I think we’re on Elm 0.17 or Elm 0.18 still. At least at the time we shipped the first version, it was larger than any example app I’d seen and there weren’t a lot of non-toy applications or examples to compare against.

I certainly have overall positive feelings about it, with some frustrations (like any language really). I’ll say that the most stand-out thing about that code is that I can be off it for six months, come back to it and within an hour or so I’m back to comfortably knowing what’s going on.

I’d played around with functional languages before Elm; I’m a bit of a language nut. One thing that’s easy to forget is how intimidating the syntax can be to people who haven’t seen anything like it before.

I don’t know that I would do such a large project in Elm again though. Or at least, it’s not something I’d push for wider adoption within work; some has to do with factors like finding developers and fact it’s just really early days for the languages in the grand scheme of things. It needs more time to grow.

On the technical side, having subpages and doing the routing of messages can be really painful and I don’t really like the ‘huge flat data model’ approach. I abstracted the core routing boilerplate away by using a JavaScript templating library to make a boilerplate generator. You specify the screens you want and your main.elm gets generated from a template, with the appropriate message routing and handling for update and view calls and the structure of the top-level data model being generated for you into an Elm source file that actually gets compiled. it worked out for us, but I still feel like it’s working around a shortcoming of the language.

Since you are a language nut, I would like your opinion on the language I've been developing for more than a year now - Mint (https://www.mint-lang.com) :)

It's something between Elm and React (while actually using React as a platform) with a lot of built-in functionality like routing, styling, data storage and more.

Wow that's cool, components as first class citizens. The native control flow structures are also pretty innovative!
This looks really interesting, and I'd certainly consider trying it out for a personal project.

If I may ask a question about syntax... Mint `render` returns look so very close to JSX syntax, but slightly different. It appears bare text variables are annotated `<{ varName }>` rather than `{ varName }`, and the `<Component::style ...>` syntax is unfamiliar. What is the motivation for providing a syntax so close to JSX but slightly different?

For this particular syntax, the motivation here was to make it look like more of a tag than an interpolation.
By huge flat data model do you refer to the sum type which basically holds your app's state? I've always wondered how that state management approach scales when the codebase grows, never seen a good example of a large scale web app architected with Elm.
Most of the hand-on experiences I have read talk about some frustration and pain working with ELM, like talking to and from native javascript libs.

Do we have a list of pain/frustrations in the X language/framework based on hand-on experience?

People and language/framework experts could share their advice and suggest better ways.

Elm has been out a long time and that is a really short list. Are there key reasons elm hasn’t seen more adoption? (Please don’t bother with comments about corporate drones etc.... companies are pretty good at taking advantage of a good thing)
From what I have heard, most teams that don't opt to Elm have a reason along the lines of: But this is not React and React is the best!

On the other hand, I have been using Elm for solid 4 years, and there are so many moments of Pure Joy of working with Elm, that JS/TS is unbearable.

I have dropped many offers to work on React TS codebases, because that kind of language is such a downgrade after Elm ... IMHO

I feel exactly the same way about Clojurescript and Reagent.
> companies are pretty good at taking advantage of a good thing.

I ... don't think that's true?

There are lots of "superior" technologies that just haven't won. e.g. the handful of people who use it _swear_ by Datomic. And there are load of so-called "inferior" technologies that are still widely relevant. Mysql? Php? Wordpress? They pay a lot of software developers' bills.

I work at NoRedInk, and we pay Evan Czaplicki to work on elm. When we started to migrate to Elm, our eng team was under 10 people. Larger companies, e.g. even NoRedInk today, tend to be less agile.

> companies are pretty good at taking advantage of a good thing

This is not my experience at all.

I don't know about anyone else, but I had some trouble with Elm. It's hard to reason in the type system (in comparison to Haskell), and I even had trouble just getting a drop-down list and radio buttons in a cross-platform way. The application structure is also very confusing to me, it's not quite MVC but it also doesn't let me just put stuff in one file. On the other hand, the workflow was good (even if it takes some time to compile + assets etc.), but I don't know if I'd use Elm again instead of trying TypeScript.
> I don't know if I'd use Elm again instead of trying TypeScript

I'd use PureScript next, or maybe ReasonML.

Elm is stagnant and its dictator seems to be quite insistent on keeping it that way.

I think you mean stable. I’ve been more productive and happy in Elm than with any other language in the past 20 years.
I tried introducing Elm at my workplace and failed because:

1. Development of compiler and core libraries strictly BDFL driven (at least used to be)

2. Fixing some important compiler/library bugs takes years

3. No way to host private package repositories

I still use Elm personally, although these are very valid concerns.

It was also rejected at my workplace, with the extra reasons:

4. The language is still unstable. Porting our code to the next release could be a huge task.

5. Elm + JavaScript is generally painful.

6. Few libraries, some of them unmaintained. Combined with the near-impossibility to use JS libraries from Elm, it would increase our work too much.

I did a side project in it; then the dependencies broke because of a compiler update (frustrating), and that's never been updated.

I would never use such a thing in production.

> Elm + JavaScript is generally painful

Getting rid of kernel modules for everything others than core packages in 0.19 made JS <-> Elm interop even more painful and broke some apps. I forked the compiler [1] to support that, although it is not upto date (still stuck at 0.19.0)

[1] https://github.com/Checksum/elm-compiler

6. Name one language, that has no unmaintained libraries, please :)
> 2. Fixing some important compiler/library bugs takes years > > 3. No way to host private package repositories

That's kind of related to the dictatorial community management. Relatedly, you still can't write a generic sort function.

You can either write a comparison function that returns an Order, or a function that converts your type to a comparable. Then you use List.sortBy or List.sortWith. I don't really know how a generic sort function would work without typeclasses/interfaces.
Elm has been around for a long time and yet it's still pre 1.0. AFAIK there hasn't been, and still isn't, a promise that what you write has any sort of forward-compatibility with the next 0.x release.

On that note, it's interesting that publishers have already put out print books.

It is just a number, react-native is not 1.0 too and it's is used in production world wide
If it was just an arbitrary number then I wouldn't have been able to write the rest of my comment. Elm has history of adopters being surprised by the hammer coming down.
https://semver.org/

'If you have a stable API on which users have come to depend, you should be 1.0.0. If you’re worrying a lot about backwards compatibility, you should probably already be 1.0.0.'

To a significant part of the community 1.0 means a stable API with considerations of backwards compatibility.

I know many people aren't using pure semver but the implications of a 1.0 have in my opinion extended beyond that point and beyond semver in general.

> that is a really short list

But was it a well-known list before this? I hadn't seen it, and know of a few projects that could have been on there.

What I'd like the list to include, though, is some references to the companies discussing using Elm. Pros and cons, the scale to which it is used etc. For instance for Vy there is this blog post: https://blogg.bekk.no/using-elm-at-vy-e028b11179eb

- no private repos (the standard PKG manager assumes GitHub). You need to use another package manager

- yearly updates in the official blog - it's very hard to convince a team when it smells like abandonware - besides not being. The fact that the language has a single centralist owner does not help (just look at the blog posts, it's always "I did this, and that", not "we".

- active work from the owner to shut down another PKG manager (Pine, if I recall correctly), because it allowed usage of """kernel""" modules

> - no private repos (the standard PKG manager assumes GitHub). You need to use another package manager

Yes, but a minor point I'd like to make is that because of how Elm is organized, you just put stuff in your src folder and it immediately compiles (since there's no JS FFI etc.). So it's not as big of a pain as it might seem.

Weird community which seemingly has Stockholm syndrome.

Relatedly, no mechanism for writing a generic sort function a la typeclasses or modules.

You have been outed for spewing elm-hate just yesterday, and now you're all over this thread as well https://news.ycombinator.com/item?id=22236258
(comment deleted)
He's actually right. The community defends even bad decisions that come from the BDFL (more like just the DFL) and cargo cult parts of the language like ports or the inability to interface with native JS code.

And there really aren't any ways to make generic functions.

Have you considered that the community just agrees? I'm happy with Elm and I don't want to sacrifice the spirit of it, just to get "big" like react or whatever. If you want to be mainstream, then there is already mainstream.
> I'm happy with Elm and I don't want to sacrifice the spirit of it, just to get "big" like react or whatever.

This part seems to come out of nowhere? Your parent disagrees with certain design choices, but they didn't say why they disagree, and it seems unlikely to me that they disagree because they want elm to go mainstream.

Unless you think that making different choices would turn elm into something mainstream? If so, I'd be interested to hear justification for that.

Yea it's a bit of a strawman. It's because I've tried to follow these discussions, and usually it resolves around that.

> Unless you think that making different choices would turn elm into something mainstream? If so, I'd be interested to hear justification for that.

I don't think it would. It would end up being just another coffeescript without any notability. It is precisely so interesting because Evan is being pragmatic. No matter where it ends up, until now at least it is far more valuable and interesting than just another kitchensink.

> It's because I've tried to follow these discussions, and usually it resolves around that.

Fair enough. That hasn't been my experience, but it's not important.

> It would end up being just another coffeescript without any notability.

Ah, perhaps I was unclear. By "turn elm into something mainstream", I meant something like "make it indistinguishable from other mainstream things with nothing to distinguish it". That sounds like what you mean here.

In any case, I don't think this is true, and I'd still be interested in hearing your reasons for thinking it.

(For example, are there specific design decisions that you think (a) people are clamoring for Evan to make differently and (b) would turn Elm into something that isn't distinguished from anything else? I can't think of any. Parent seemed to be referencing kernel code, but Elm 0.18 had that, and it wasn't just another coffeescript.)

> It is precisely so interesting because Evan is being pragmatic.

What do you mean by "pragmatic", here? My natural interpretation would be "Evan is making compromises to the core design to make Elm easier to use", but that doesn't seem to fit. If that's what you mean I just plain disagree, and I think Evan would too. (Though, again, if that is what you mean then I'd be interested to hear your reasons for thinking it.)

On the contrary, I mean that Evan sometimes makes Elm harder to use, for a long term vision.

E.g. kernel.

I guess what I'm saying is that the community treats Evan Czaplicki like some sort of language design god who has carefully and artisinally crafted a revolutionary new language with no runtime errors(!!!!) when in reality it's just Haskell with all the powerful features stripped out.

I really do like the paradigm of unidirectional data binding to the UI and the message system, but Elm The Language itself is basically the Go of functional programming; when you point this out on the subreddit or to a fan, you'll get banned (I have) or condescend to in the most obnoxious way, with plenty of the word "folks" peppered in.

Add brilliant.org to the list.

I'm currently not in the position to do a pull request.

Not looked at Elm before, but it does look interesting
I'd avoid it. The community is weird and the language is hobbled in various ways and they insist on keeping it that way.

I'd try PureScript next, or ReasonML. But not Elm. Definitely not in production.

"weird" but in a good way
I think Elm has two major things that make it such a pleasant detour from what most of us have experienced building web clients:

1. It comes with an opinionated architecture for building apps (model, view, update loop): https://guide.elm-lang.org/architecture/. This constraint is a breath of fresh air if you've ever installed React and then been stuck wondering how you should deal with state. Mobx? Event emitters? Redux? And your app increasingly niches itself into a novel constellation of dependencies. Meanwhile, Elm apps are basically all the same from an architectural standpoint.

2. Strict type system, great compiler errors, no runtime errors. I think the best illustration of this is refactoring power. I've come back to old projects where I certainly don't remember how the code works. I start writing the code that my feature needs (like changing the html to rely on variables I haven't yet defined) and I basically just follow the compiler errors until it works. Or I've made massive refactors like added an archer class to my game that was previously just melee classes which introduced daunting modeling changes to my system, and the compiler essentially gave me a TODO list of all the code sites I needed to update.

Elm certainly involves learning new things, but there's also a lot of work in stitching together a similar concoction of React, Typescript, immutability, etc. In many ways Elm is a vast simplification.

I feel like Elm has been stalling a bit the last year. Communities in my area are less vibrant, and I feel like I hear about it less than say 2 years ago.

But where we used to have only 1 european conference in 2017, there are now at least 3. The list is still short, but growing and there is no crazy push for adoption so it's understandable.

Most of the core libraries haven't been updated for over 2 years, which is OK, since they work :). That's something that is quite far from the 'there has to be noise about it' habits from our tech world, and it might be one of the reasons it doesn't raise.

I still love writing it more than anything else. Elm makes me happy, more than anything else I've ever written, and that's all the counts for me

> Microsoft - the world's second largest software company, has used Elm for the frontend...

Should I take the list with a grain of salt? Just kidding, I'm just curious which they think is the first.

I guess Oracle has more employees? Or perhaps they’re using a wide definition of software company.
Interesting that the list is so heavy in education.
The company that employs the author of the language (Evan) is NoRedInk, an edusoftware company, so that may be a large reason.
As I understand, some of companies don't know that they use Elm: they paid money for "some modern frontend" and got it written in Elm. It looks like deliberate technological lock.
The company I work at (https://halogen.tv) has been using Elm in production for a few years now, we have around 90k LOC in Elm for the front-end, and it has mostly been a pleasure to work in.

The biggest upsides in my view are:

- The compiler is your best friend, the error messages are great, and you can enforce a lot of things with the type system. Have a list that should never been empty? Use a NonEmptyList, need to manage a selection? Use a Zipper/SelectList. Forgot to handle a possibility in a case statement? The compiler will catch it for you.

- Refactoring, even large scale refactors, are tractable and actually fun. Change the architecture in whatever way you want and follow the compiler errors, when you fix the last compiler error things usually work like you want!

- (Almost) No runtime errors. There are still a few rough edges where you can get a runtime exception, but they are uncommon.

It is not to say it is all roses, there are negatives as well:

- Lack of a roadmap or timeline, there is zero visibility into what is being worked on and when things may happen. This has been a deliberate choice by the core team I think because when they had a roadmap and parts of it didn't fit into the next release people were angry.

- Bugs can take a long time to be fixed, even if there is a PR that fixes it, it is unlikely to be merged.

- Experimentation is discouraged. The 0.19 update removed the undocumented, unsupported, here-be-dragons hooks that allowed writing effect managers except for repos in the elm or elm-explorations organizations on github. I agree with not allowing those modules to be published to the elm package site, but intentionally blocking people experimenting on their own is unnecessary in my opinion. Of course you can always fork the compiler and remove the restrictions.

- Ports are a pain. We generally use custom elements in place of ports where it makes sense, but they are really a hack around some of Elm's pain points, if I could do it all nicely in Elm I would.

> - Lack of a roadmap or timeline, there is zero visibility into what is being worked on and when things may happen. This has been a deliberate choice by the core team I think because when they had a roadmap and parts of it didn't fit into the next release people were angry.

this is a bit sad (the fact that mobs are still mobs)

in any case I wonder if they couldn't make some kind of core partner club with people that have been long and deep Elm users

I've always seen Elm as being between a rock and a hard place socially. On the one hand, a lot of people with no FP experience dismiss it for being a "weird" FP language. On the other hand, a lot of people with FP experience dismiss it for not having some FP feature they really want (e.g. one that keeps coming up and just won't die is typeclasses).

Also there is a core Elm team consisting of something like half a dozen people, unless you mean a partner club of e.g. tech teams that use Elm.

I have an immense amount of respect for Evan Czaplicki for how he tries to thread the needle here and the huge amount of thought and craft he puts into the UI and UX of Elm to make it accessible. Unfortunately you can't please everyone (hell he doesn't even please me with all his decisions, the gall of him! ;)) and Elm has had its share of vocal naysayers. Elm may or may not die out, but the impact it's had on raising the bar for the UI/UX of dealing with a compiler has been IMO one of the most valuable advancements for statically typed languages in recent years.

> a lot of people with FP experience dismiss it for not having some FP feature they really want (e.g. one that keeps coming up and just won't die is typeclasses).

You still can't write a generic sort function. It's not only typeclasses, there's also no module system and Evan is patronizing about it.

> this is a bit sad (the fact that mobs are still mobs)

Not that people in open source can't be entitled, but the way Elm handles the community is awful and patronizing. Also they make too many breaking changes for me to write code in Elm.

Ah in that case I stand corrected. In any case dealing with others is .. subtle.
Be careful taking his words as a correction, he is being toxic about elm all over the place.
My team has had a similar experience - the gap between 0.19 and 0.19.1 was really frustrating.

I'm curious what your problem is with ports? In my experience it's a nice API for interacting with the outside world. Or are you referring to DOM features that haven't been mirrored in Elm yet?

They are fine for a general FFI mechanism, and in certain cases they fit into the code very nicely (e.g. websockets fit the publish/subscribe pattern very well), but for handling events from the DOM or interacting with existing JS libraries it breaks down a bit.

For instance, we have a text editor that wraps Quill so that we can support things like mentions, hashtags, and emojis. We can have multiple instances of the editor on the page at once, so the port needs a way to uniquely identify which instance the event is for, and handle delivering any responses to the correct instance of the editor. I find it a lot easier to partially apply the ID of the editor to the message so that everything is defined where it is used in the code. It is also possible to forget to add the necessary subscriptions when adding the editor to a new page, whereas with a custom element it is all handled internally.

Another case where ports had a bit of an impedance mismatch is on using existing browser APIs, like the Intl module (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...). We wanted to use it to format an epoch time into the user's locale. The only way to call the Intl module from Elm itself is through ports, and the wiring makes the code a lot more complex because you have to send the request out through a port, wait for the response, and then render it. With a custom element it becomes a lot simpler conceptually, we have something like

  DateTime.view posix
We also like to wrap up the custom elements with a type-safe Elm wrapper so that we can control what options are available. We have some feeds that have infinite-scroll on them to load more content as you reach the bottom, it uses a custom element that wraps the IntersectionObserver API and fires events that Elm can listen to, so it makes it really easy to use and understand how it is working, in the code it looks like

      InfiniteScroll.view
        { onScrollIntersect = LoadMore
        , state =
            case feed of
              Done ->
                InfiniteScroll.Done
              Failure ->
                InfiniteScroll.Failure
              Loading ->
                InfiniteScroll.Loading
        }

Anywhere you want to respond to scroll position you can just add that element in and it will work its magic.
I’d really like to understand more of this. Any chance you could make an Ellie or something to demonstrate?
I don't have one on Ellie, but Ellie itself has a nice example with how it wraps CodeMirror (https://github.com/ellie-app/ellie/blob/master/assets/src/El...)

I don't know if there is a formal name for this pattern, but we've been calling in the "un-attr" pattern, you define an opaque type like

  type Attribute msg
      = Attr (Html.Attribute msg)
And then expose functions that allow you to set attributes you whitelist. In the JS you use setters to hook into when the attribute changes and respond to it (https://github.com/ellie-app/ellie/blob/master/assets/src/El...)
For me the annoying thing about ports is that it makes any interop with a JS library of pure functions frustrating. For example, let's say I wanted to use the math.js library. I have a string expression I want to parse and calculate into a mathematical result.

math.js has a nice `math.evaluate` function for this, that in theory would have the type `String -> Result ParseError Float`, if I could directly assign Elm types to a JS function. However, I can't actually use the function like that. I must treat it as a pub-sub mechanism and define the requisite messages, state, update functions, etc. in order to use it. This turns what should've been a one line call into potentially dozens of lines that also forces an architectural change in how the calling code actually calls the function.

The only other real alternative is to rewrite the functionality I need in Elm.

I guess Evan really wants that function to get rewritten in Elm - after all it's synchronous.

There should be some built-in asyn request/response mechanism for ports, in the style of the Http module where you specify a Msg for the response. This would work for synchronous stuff too.

For years and years people have been asking for "task ports" which would facilitate synchronous but safe js interop.

As far as I can tell the only reason Evan doesn't include something like task ports is to purposely make interop less convenient (but no more safe) than it needs to be, in order to encourage people to write elm. However, I think this decision will end up biting him at the end of the day.

These companies are using an older email client? Great! How does that affect me, and how does anyone else know specifically who's using elm?
No not the email client. It's about choice of timber for TV studios.
I have hard criticism about Elm, but I concur that it has a good onboarding experience when compared to PureScript, Miso and GHCJS.
We at PINATA (gopinata.com) just built one of our newest features with Elm and Elm UI.

We finished it on time, which is already uncommon and especially when you don't have any real prior experience with a new language. We shipped it to production, and it has been working flawlessly!

The simplicity of Elm fundamentals make the language easy to learn, your code readable, and the solution to your problems almost obvious. On top of that, the "If it compiles, it works" feeling helps you trust your code and prevents most of the bugs introduced in refactors.

We aren't going back any time soon :)

So... uh... which of these companies are hiring?
We're in the process of a rewrite into Elm at the moment and have been loving every moment of it. Even the devs who are seeing Elm for the first time are enjoying it.