Elm 0.19 Broke Us πŸ’”

kspeakman profile image Kasey Speakman Updated on ・6 min read

Elm 0.19 was released yesterday. There were a significant number of breaking changes at every level: configuration, tooling, library, language. But those are not what this post is primarily about (edit: and Elm provides an upgrade tool to autofix many of these things). For my team, this release broke our hearts.

Two changes that placed the proverbial "straw that broke the camel's back": Removal of custom operators and native modules. At first I only saw the removal of custom operators, and I posted my reaction to that here. The removal of native modules was not mentioned in the 0.19 release notes so I didn't find out about it until today. I just happened to think of it, and a search turned up this post.

The post on native modules was back in March, so how did I not know about it?


I disconnected from participating in the Elm community a little while back. I didn't say much about it at the time, but I'll share the reasons. I love the Elm platform and use it, but decided that the way the community is managed is too frustrating. The tone is firmly set by the way the Elm Github issues are managed. Many of them are locked to prevent disagreeable feedback, or because they are personal items only for the blessed few contributors, even though they are in public. If you post an issue, you are likely to get smacked on the hand for not doing things "properly". Properly means a rigorous SSCCE for bugs, or participating in the gladiator arena of public forums for ideas/requests/suggestions, or you can forget both of those things if you went the extra, extra miles to be trusted as a contributor. I say gladiator arena, but the Elm community is really very nice in general, especially for helping newcomers. However there are more than a few people who have their rulers out and ready to smack that hand to enforce whatever Evan (the creator of Elm) has said or not said. So chances are high that posting "ideas" or "feedback" on the forum will result in being chided. This, in turn, justifies that there was no "agreement" on your post among the community so it can be ignored. So the "go post on the forum first" rule is an effective way to ignore feedback.

Apparently since Elm forums have moved to (edit: Reddit and) Discourse, threads there can be locked too. When mods know Evan doesn't want to hear your disagreement on a particular issue, they may preemptively lock posts where it might surface. In the end, it feels like the D in BDFL is taken a little too seriously over there. So I appreciated the product but mostly stayed away from the community, and didn't happen to catch the posts telegraphing changes.

To be fair, I did have a bad experience myself, and have fault in that. But I have observed this pattern of unwelcomeness in Elm's old github and google group many times as an onlooker. And it isn't this way in other projects I've worked with.


The removal of custom operators was ostensibly for the good of Elm. However, in the post explaining the reasoning behind their removal, an estimated 5% of users have them. And several of the reasons for using them are in common with other languages (task chaining, parsing). In the end, specific custom operators were blessed by Evan and were allowed to remain as exceptions to the rule. But whatever ordinary Elm users think is a valid custom operator for their use cases is "bad" for Elm. Okay...

Theoretically I can still inject native modules through monkey patching in 0.19. (Javascript, right!) However with dead code elimination, monkey patching could be a bit difficult unless you turn off optimizations. But the real kicker is that native modules are still there. They are just reserved for a few Elm contributors only. The rest of us should not have access to this expert feature. Apparently the 40 total lines of native code that I use will completely break the Elm community. Even though there is no other reasonable way to do what I need. Okay...

Minor but indicative: Evan has posted many times telling users to change the way they talk or think about Elm. (Fair point: he's nice about it and there are valid points. But still... indicative.) Examples: Don't use the word Components. Don't say "native"; say "kernel" instead. Union types should now be called Custom Types. But don't you dare respond to one of his posts -- there is always a closing section instructing you of the only few acceptable replies or to just not reply at all. Okay...

Considering all of the above, a picture is forming for us: we can expect to be overbearingly micromanaged as Elm users. And feedback (well, disagreement) is not welcome or considered even when it is decisive and voluminous, like on native modules. Evan decides he just doesn't like something he sees Elm users doing (even if it has credibility from similar languages, like custom operators), it gets disabled in the next release. My way or the highway. Despite all the amazing things Elm has been to us, that's intense behavior for a toolchain. And not really a situation my team wants to be in.

What now?

The way I see it, we have a few options.

Keep using 0.18

I have not had any major issues with 0.18. We could avoid the broken things that have been pointed out in the changelog (like Arrays). However, this is not a long term strategy. It seems unlikely that 0.18 will ever see another bugfix. Old versions of tools (like Create Elm App) eventually stop being maintained. Meanwhile Computer Science and the web advances on.

Monkey patch 0.19

Because of the dead code elimination, putting the formerly "native" code in through monkey patching has some unknowns. But the deeper issue is that by moving to 0.19 we are still in a place of feeling unstable with the future of our toolchain.

Wait for an Elm fork

Lots of tree names are probably still available (i.e. acacia, poplar, etc). Unfortunately we do not have the resources to maintain a fork. But it seems likely that somebody will draw similar conclusions to us and be in a place where they want to create one. Even then, this path has a lot of unknowns.

Wait for Elm to solidify

Most projects reach a phase where they solidify. Meaning there is some effort to maintain backward compatibility. If Elm decides to do this at some point, we could evaluate where the latest version is. Maybe by then there legitimately won't be a need to have the freedoms which were taken away, so it will be a moot issue. However, probably as long as Encoders and Decoders are the only official way to deal with JSON, we will need native code. 20 lines of native code saves us hundreds of lines of encoders and decoders.

Switch to something else

The only other Model-View-Update platform I'm aware of is Fable-Elmish. It uses F#, which we already use for APIs anyway. The unfortunate bit about that is that F# is not a pure language. So it takes discipline to write pure functions. Whereas Elm has been taking purity too far with some of these recent changes, F# is not quite far enough IMO for the front end. But F# is great for APIs since they are about integrating external systems (e.g. UI, database, email, files, etc). F# would be harder to use there if it had a lot of overhead to perform side effects. Striking the right balance for the use case is important. Anyway, it is still an option on the table.

There could also arise an alternative MVU platform at some point. I believe ClojureScript has a library which works similar to MVU. I don't really want to go back to a component-based system. (Yes, pure function MVU is that good.)


The team has all agreed that sticking with 0.18 is the best choice for us right now. We have some apps coming up that we will create with 0.18, ignoring 0.19. We will experiment with Fable. We will see if another MVU style platform is around. Eventually 0.18 will start to rot and we will need to switch to something else going forward.

We find this situation really disheartening. We love Elm and never wanted to use anything else. But we have begun to feel that our relationship with Elm is unstable. πŸ’”

Posted on by:

kspeakman profile

Kasey Speakman


collector of ideas. no one of consequence.


markdown guide

Minor but indicative: Evan has posted many times telling users to change the way they talk or think about Elm. (Fair point: he's nice about it and there are valid points. But still... indicative.) Examples: Don't use the word Components. Don't say "native"; say "kernel" instead. Union types should now be called Custom Types.

I think this is the only thing about what you say that I disagree with a bit - terminology is important, and it's important to try to keep reminding people to use the same terminology not to confuse people who don't have a solid grasp of what you're talking about.

This issue is even more important when you're dealing with non-technical people, but it's very important with beginners to any technology too. If you have 5 ways to say the same thing, people are going to get super confused.


Ironically, a lot of time is wasted trying to figure out what "name" elm uses for existing FP concepts, so many thing have names entirely different to more standard OCaml, Haskell, etc. names.


I believe the reasoning for this was that the FP people will understand the concept anyway, and the beginners to FP will understand the non-FP terminology better.

Right, thanks, so that is failed reasoning.

  1. The people fluent in FP will waste a lot of time figuring out the mapping of terms
  2. The people not yet fluent in FP will waste time later (when moving to a usable language such as Purescript), figuring out the "proper" name for the stuff they learned.

Also, it's not that Haskell "invented" the names, most come from research papers in FP and are established concepts there.

Imagine writing a new "better" textbook on biology and renaming all the terms. Doesn't make sense...

Also, come to think of it: The whole point of a symbol like <$> would be to not really indicate any "intuitive" understanding of what it does; just remember the type and learn to apply it. The understanding should remain abstract...

This is pretty much in line of the "No Abstraction" attitude of Elm; makes sense, but wrong...


I'm sorry that your experience with the community has been negative.

To be fair about the operator issue, Evan has removed a couple of operators from the std-lib in 0.19, but kept a few that makes a ton of sense in web development (like </> for url path separators). Experience is that a name is much better than an operator except in the few cases where an operator is universally known.

Out of curiosity, what sort of cases are you not able to do with ports or custom elements and must use native code to do?


Thanks for your comment Robin.

I read the post on operator removal. Did you happen to read my response? Some of your observations are addressed there. So the interesting bit about that is: if you read how the URL parsing library came about, the idea was based from another language. That's also how the custom operators </> and <?> were brought into Elm. First as a personal library. And now an Elm package, enshrined as exceptions to the "no custom operators" rule.

Without custom operators, this same discovery and experimentation process is now blocked to ordinary Elm users. Were someone to discover a new use case that an operator would be great for, they can't choose to use it themselves or experiment with it in Elm. They would have to beg for an exception.

Their removal also implies that whatever custom operator you were using for a specific use case (not a general solution) was wrong and you can't have it anymore. There happens to be significant prior art that says otherwise especially within the family of languages that Elm descends. I came away from Evan's post thinking there is no clear problem with the custom operators, but he decided to take them away -- knowing users are using them -- anyway. This is a pretty intense way to deal with your users.

I might have been a little overwrought with the "no other reasonable way" comment. There is usually always a way to do something, but it might be too painful (hence unreasonable) for us.

The primary thing Elm fails to do for us right now is type-based JSON de/serialization. Elm's built-in encoding and decoding is great for fuzzy APIs. However, that is not a situation we find ourselves in. For us encoders and decoders are an intractable solution which creates at least hundreds of lines of redundant/difficult code to maintain. Instead of that, we define a port, and call the 20 lines of native code to extract the auto-generated encoder or decoder from the port. The alternative is to invest in creating an external code-gen tool for encoders and decoders. Another tool to maintain and be familiar with.

The second usage we currently have is for file uploads. Elm has no built-in support for this. For now I have 20 lines of native code that converts the javascript File into something that the Http module will send. Basically, it smuggles the File(s) thru Elm as a StringBody. Http module just calls xhr.send under the covers, so it works fine. I did recently find an Elm only solution to this that might work.

I had every intention of switching away from these native solutions once Elm has fleshed out something better. But in the interim, native was my way to fill in missing things myself. Now that avenue has been removed, and I wouldn't characterize Elm's API complete. Worst of all, the main reason it was removed was just because Evan didn't want ordinary Elm users to have it... just blessed Elm package devs. It makes me sad.



I can't disagree with you that experimentation with operators is now harder. But the reason for their removal is that operators is very rarely more readable than named functions. While you're right that there is a lot of prior art when it comes to good custom operators, most of the custom operators in Haskell (for instance) are, imho, horrible.

Operators can make reading code easier, but only when everyone immediately understands what the operators mean and this is only true for a very small set of operators. When Evan decided to remove custom operators it was because he scanned through the packages repo and found operators like -~>... what does that even mean?

Regarding the "this is a pretty intense way to deal with your users." comment, we need to focus on what Elm 1.0 should look like. At that point, things like this won't change anymore, but before that point Elm should remove things which isn't necessary to the language. That's the only way to make it easier for professionals and beginners alike.

For JSON encoding/decoding, I understand your pain as I initially thought about them that way. But I've come to view them as assertions that what I'm given from the backend (or browser) as correct, and makes me write code that deals with them if not. I also use them to convert certain constants into union types. Besides, encoders/decoders rarely change, so they're low maintenance. There are several code generators for encoders/decoders (like this one noredink.github.io/json-to-elm/), but I've not really felt the need for them.

File uploads is something that is lacking from Elm, and I hope that it's something coming soon. However, you don't need native/kernel code for this. A port should work just fine for this use case.

A lot of opinions here that are different from my experiences. Some people use odd operators. We don't -- just the common ones for bind and map. But even if they do, who cares? It's not likely to be used when people are intimidated by the operators. It's a freedom that really didn't have to be taken away. Some people really need encoders/decoders. 99% of our API calls don't -- the types always line up exactly, and we do adjust types regularly. So maintaining co/decs has only downsides.

For files, I agree a port is perfectly fine. At the time I could not find a succinct example for that, and it was just quicker to do what I did. But were I doing it again, I would probably use this as a guide.

They're not my opinions, it's my experience. I came to Elm from languages which much more constructs. Nowadays I spend most of my time in languages which are very small (Elm, Go...). I don't miss the days of C++, C# or JS.

"It's not likely to be used when people are intimidated by the operators." <--- This is wrong. If there's really only one library which provides what you need, and that library uses operators, you have to use them. If you're fixing bugs some other developer wrote, and that developer is fond of operators, you have to use them. There are other situations as well, but the idea that people who don't like a construct will avoid it, just doesn't work out in practice.

Operators, while nice in certain cases, doesn't enable something that wasn't possible before. Unless they're universally understood, writing a function with an easily understood name that can be used in a pipeline is just much easier.

I can agree with you that operators can make code more cryptic and should be used sparingly. But I disagree that everyone's choice about using them should be taken away. It would be one thing if they were blocked from published packages, but they are not even allowed in my app code now. That's just being controlling.

Your perspective is valid, but (my own opinion, not necessarily Evan's) since Elm is still pre 1.0, I think the perspective from the language creator is not "what can I take away" but "what should be in the language when it's done."

So while the users of the language in the current state feel som pain through breaking changes, I think Evan has a 20 year perspective on things. And in 20 years, will Elm programming be worse or better off because of custom operators? We can disagree, but my experience with Haskell is that Elm is better off without.

But yeah, I get that it's frustrating that a feature you use is removed.

Ah! That's the difference. I'm coming from F#, which has custom operators. But it has not really gone overboard with them. Without HKTs/typeclasses it is not easily possible to define an operator once and have it apply to different types. You have to define the operator for every containing type, and then you can end up with naming conflicts if you overdo that.

So in practice, the operator really has to buy you something to bother, and it stays limited to a specific module. Probably the worst offenders I've seen are libraries ported from Haskell. But since they are limited to that library, I can just use a different alternative, or in small cases just write my own. So my experience with custom operators has been drastically different, and I have found them useful in F#. For example, I ported Elm's URL parsing library to F#, and because custom operators were allowed was able to use the </> and <?> operators. If I find myself in the reverse situation, I would be stuck in 0.19.

But yeah, I get that it's frustrating that a feature you use is removed.

I use this feature in Elm almost not at all, currently. I could easily get by without it. (But I have needed it in F#, so view it as useful and a mistake to remove.) As mentioned in the original post, it's the overall message that we're getting from Elm that has me reeling. Not just this one piece.

I wholeheartedly agree with this.

"what should be in the language when it's done."

People have been suggesting countless of things, type classes, SYTC, HKT, etc etc... those issues get closed with comments such as "use another language then" or "almost nobody uses this".

I am actually suspecting that nobody really knows how to implement these features on a theoretical level and that's why...

The implementation for these things are known, there's just no pressing need to introduce them to the compiler. There's also no consensus on what the right implementation would be.

I write Elm full time, and don't miss these things. There have been times where it would be nice to implement comparable for one of my types, but I'm not convinced that type classes is the right approach for ad-hoc polymorphism in Elm.


I did recently find an Elm only solution to this that might work.

You got me curious, what are you thinking about?

Well, I thought maybe I could make it work when I found this function which basically decodes the event.target.files[0] into a Value. The MIME type should also be available by decoding the type property off of this.

However, the only way to convert a Value into a Http.Body type currently thru Elm is with jsonBody. And when I traced that all the way down, it is going to fail to work for 2 reasons. First, jsonBody sets the MIME type to "application/json" always. Even if you set the content type in a header, StringBody's content type is evaluated last so it will probably overwrite or concatenate whatever else you set with "application/json". (This is a problem for my use case anyway.) Second, jsonBody calls Encode.encode on the Value which calls JSON.stringify in javascript. In my quick search, this will neither stringify the file contents nor keep the JS File object in tact. So it will not upload the file.

So, nevermind. I still need to do it with native code (edit: or a port to Javascript) currently.

For the MIME type, this is not a problem, you can define your own function like:

rawBody : Decode.Value -> Http.Body
rawBody value =
    Http.stringBody "application/octet-stream" (Encode.encode 0 value)

Encode.encode is another story. JSON.stringify could be monkey patched to return File objects unmodified, but encode is actually JSON.stringify(...) + '' (since 0.19), so even if stringify preserves the file, encode will still return an "[object File]" string because of type coercion.

Anyway, using a port with readAsDataURL and uploading base64 encoded files is not so bad, are the overhead and server decoding really an issue for you?

Anyway, using a port with readAsDataURL and uploading base64 encoded files is not so bad, are the overhead and server decoding really an issue for you?

Nah. At the time I couldn't find a succinct example with the FileReader stuff. The one I found still used native code and also had a lot of extra abstractions to wade through. So it was quicker to just do what I did. But I'm not married to it. I did find a pretty clear port solution with FileReader that I would use now.


I'm a bit late, but I have a really good use for custom operators. I had a project that dealt with types, so I had a custom arrow operator so I could write functions like a => b => c. I also had operators related to composing lines of code that my program generated.

In my opinion disallowing Javascript is the correct choice because Javascript modules can be security threats and not having Javascript makes Elm libraries usable when compiling to something else.

On the other hand disallowing use of harmless expert features is stupid. Custom operators are a feature that beginners don't need to know about. Removing it is like removing plus and minus.

The stated reason that naming operators is hard could be solved by giving back the ability to call functions in an infix position or allowing overloading of functions. The latter would also get rid of appendable, which in turn would get rid of the ridiculous compappend.

I even found a bug related to this by just glancing at the implementation one day. github.com/elm/compiler/issues/168...


The problem is that beginners can't simply ignore them. They're usually faced with them because someone on the project thought it was a good idea, or because the only open source library which provides x also makes heavy use of operators.

And that's the thing about operators: when you have a good operator it makes the code easier to read, when you have a bad one it makes the code much harder to read. I personally only really like the piping operators, but then again I'm a Lisp guy.

Overloading functions makes things harder to understand in general (wait, which version of that function is called now?), and is difficult to combine with currying.

My point is that beginners already have to deal with operators. Adding some badly named ones is not worse than adding badly named functions. I have taught beginners and have found that they are confused by the fact that Map and Array do not have syntax associated with them.

If someone is able to use plus with prefix notation, I'm not convinced that custom operators are a big hurdle anymore.

Making your own overloaded functions is harder to learn than (comparable, appendable, number) but without overloading there is no way of making custom comparable types.

Using overloaded functions requires you to understand errors like "No version of (+) takes an argument of type Model." The current model requires understanding of comparable and appendable.

Overloads would make complex type mismatches worse, but those are not understandable anyway unless you add type annotations.

The real reason for why overloading wouldn't work is a technical one. For example a set data structure needs to work with any comparable type and the definition of (<) has to be visible to the module implementing a the set. If this could be elegantly overcome, I think overloading would be the type class replacement for Elm.

Getting rid of appendable would just require the removal of ++ for Strings, though.

Overloading [...] is difficult to combine with currying.

I think it makes sense to require that the functions have the same number of arguments.

My point is that beginners already have to deal with operators.

Beginners usually only deal with operators they already know, like +, -, * and /. As far as I've seen, most people don't use operators in prefix notation.

I'm not convinced that custom operators are a big hurdle anymore.

There's a big difference between + and -~-> though (and yes, that operator existed).

Getting rid of appendable would just require the removal of ++ for Strings, though.

Here we agree, though I'd rather remove ++ for Lists as ++ is really great for String concatenation.

I think it makes sense to require that the functions have the same number of arguments.

You'd still get a problem with stuff like

someFunc : (a -> b) -> a
someFunc : a -> a

The problem with this "Experience" based stuff is that it only considers a few use cases.

Elm would be great for us if it stuck to FRP and added meta-programming. We generate a lot of the UI at runtime instead of having hardcoded UI structure, this is basically impossible to work with in Elm.

Just because Evan doesn't write complicated code, where a symbol would make things more comprehensible, doesn't mean nobody in the world should.


"this is basically impossible to work with in Elm"

Then you should use a language which allows this. Elm doesn't try to be everything to everyone, and if it doesn't suit you, you shouldn't expect it to change to suit your needs.

We surely did move to another language.

However, I have used Elm since very first release and have seen it deteriorate. In the never-ending effort to "stay friendly to beginners", many important features are not implemented or removed in later versions.

Informed discussion about it is also not really possible, in particular because of typophobic comments like yours: "go back to your own country with your Fancy Types".

There is a certain glass ceiling in Elm that everyone eventually will run into...

And also, please note that people are not suggesting totally crazy shit, like asking Evan to add linear dependent types or something.

Think about it: we have theoretical tools for UIs such as reactive programming & profunctor optics, which are perfect for advanced UI programming and which would be so awesome to have in Elm. They would make many many things much simpler...

See, I've used Elm for a long time too and in my opinion it has only improved. While the features you want might seem important to you, they don't seem that way to me as I've yet to experience that I'm blocked on some issue because of a missing feature in Elm.

While I'm aware that there are things Elm doesn't suit for because it might miss some feature or another, I would personally expect Elm to incorporate features once it has a good design for it, that doesn't deteriorate some of the best things about Elm (like being a small language that generally does what you'd expect and gives great error messages when something is wrong).


Thanks for sharing your point of view. I'm still a fan of Elm because of the ideas it represents and how fun it was to write browser code in a functional language with a strong type system. I never got to a point where I was willing to campaign for it at work, do I like hearing from people using it on the regular.

I don't have too much to add but you mentioned exploring other options.

I took a good crack at ReasonML this summer and worked with a port of the Elm architecture: npmjs.com/package/bucklescript-tea

I only found one other mention of Reason in the comments and no mention of Bucklescript. Also, to head you off at the pass if you have beef with the Reason syntax: just use OCaml if you get it; the syntax is not the point, the ideas, compiler, and libraries are the point.

Bucklescript is fantastic, well thought out, and advancing regularly. Reason itself has a very nice JS interop story. The compiler (Bucklescript) is really smart and has had the code elimination story down for a while now.

Maybe you'll find something you like there.

Meanwhile, I'm thinking of my job where I still write CoffeeScript for a living. At least you have fun something more fun to complain about ;)


I can't believe how entitled some software developers are. No wonder why Guido stepped down recently. Just like Guido, Evan is doing his best to make programming easier for everyone, giving away his work for free, and you are mad because the new release, which you are not forced in any way to update any time soon, mildly inconveniences you?

It's super to express your opinions on the internet, but very difficult to listen to them all. Not all of them are helpful, and it's impossible to take into account all of them. Language design is extremely difficult, our industry still has A LOT to learn about it. Sometimes hard decisions have to made, and you must go with the lesser evil. If you want control so badly, why don't you fork the compiler and implement the language as you see fit?

It's not like 0.19 brings a a completely new language. Ports have been the better way for JS interop for a while now. Removing operators just means that you have to refactor your code to not use them, and the compiler already makes refactoring easier. You have plenty of time to figure out your strategy for migrating.

The worst thing about this is that outsiders are seeing this and think "Wow! Elm is such a mess, I'm glad we stuck with React/Vue/Angular.". <- This actually hurts the community, it's simply not true. There's still a long way to go, but Elm is looking good with this new release.


Thanks for your comment.

Entitlement is an interesting concept. As developers we are spoiled for choice in tools. Elm is competing for mindshare in a flooded landscape. It is a totally weird thing since it (and most of the other tools) are provided for free! However, choosing one of these tools is also an investment with an associated risk. The directions that your tools take can directly affect your projects.

I saw the seeds of unhealthiness (e.g. censorship of disagreement) a while ago. But I mostly kept quiet about them because I figured: "Ah, every place has it's problems." Usually, life has a way of working those things out over time. It didn't seem to affect the practical needs of users, so I was content to participate with Elm in my own way. On this site for example, I have often plugged Elm when people asked about tech choices and made articles about it myself. But the timbre seems to have changed with 0.19. Instead of issues getting better, they are getting more rigid, finding their way into the product, and increasing our risk in using it.

The vision of Elm is one I want to see realized. But how we were getting there was already deleterious to the community. And it only seems to be getting more so. Saying nothing (or saying something in Elm's own forums) does not help to surface the issues. Surfacing the issues is important to overcoming them. Which I sincerely hope Elm does, because it is an amazing product that I genuinely enjoy for creating and maintaining UIs. This whole thing saddens me as well.


We love Elm and never wanted to use anything else.

Judging from the rest of your post, that sounds like a severe case of stockholm syndrome ;)

Adopting a non-stable technology as the basis of a product is risky. I personally would not put too much trust on anything that isn't committed to do the utmost to keep backwards compatibility, i.e. if I had to deliver something I'd choose boring, but reliable over shiny new and sexy everytime.


Judging from the rest of your post, that sounds like a severe case of stockholm syndrome ;)

Hah. But seriously functional MVU is amazing. I've done front end projects in a sampling of the standard technologies (component-based or just vanilla) and they have real issues with regard to maintenance and the kinds of designs they tend to encourage. I did research before choosing Elm, and a test project.

We have been using Elm since 0.16 (edit: actually it might have been 0.17), and releases (including 0.19) had an upgrade guide and even an upgrade tool to resolve most breaking changes. So there hasn't been a lot of risk so far even though each release breaks some things typically.

Also the author works for a company which uses Elm for the basis of their own product. So one would think that would be a stabilizing force.

I expected that it was getting to a point of solidity. So imagine my surprise when this release dropped with breaking changes and a "too bad, so sad" mindset. Sometimes when projects do that, they will issue service releases to the old product so people can keep using it. But I doubt that will be the case here.


But seriously functional MVU is amazing.

I agree, and the pattern and amongst them supporting libraries has risen to stellar popularity in many other web frontend ecosystems as well (redux, mobx, ngrx) - for good reason.

I never looked very deep into Elm. From my superfical and cursory exposure to it I got the impression that the language was quite opinionated (which is not everyone's cup of tea, but since it tend to agree with the opinion, it would certainly not be a dealbreaker for myself) and that previous Haskell knowledge helps to a not so small degree.

I'm also willing to cut everything with a version number, that starts with 0, some slack - but I understand your frustration. Out of curiosity: could you give a ballpark figure how much manual work adapting your codebase to the 0.19 release would be? Or do you consider it to be rather unfeasible (maybe due to business reasons, deadlines etc)?

I very nearly went with React/Redux before researching Elm. I still think Elm has a much better way to work with side effects. Redux is sort of a "pick your plugin poison" situation there. I'm not familiar with mobx or ngrx.

Aside from the two things I griped about, there is one major API change that I believe the upgrade tool will not do for us. And that is the new Navigation API. My gut feeling is that the effort to adapt this will be more difficult than average. It might take a person-week or more to get familiar with it and get a large project converted over. Subsequent projects should go more quickly, no more than a few days.

For the removal of native modules, I don't think I would monkey patch what we currently use native for (see response to Robin for details on that). I probably would develop an external tool, then get the team accustomed to using it. Probably a few person-days for the dev effort. And inestimable cost for having to be familiar with, integrate, and use yet another tool.

We could likely fix whatever else was broken that the upgrade tool would not catch in a day. Including custom operators, since we didn't use them that much.

However, we aren't planning to upgrade to 0.19. The breaking changes are worse than usual, but we generally don't have a problem with them. Elm compiler surfaces breaking changes pretty well, and we like API improvements. For example, we feel the effects of wonky navigation in 0.18. The bigger issue with 0.19 is the instability we now feel with the platform.

The breaking changes aren't that big (Signals->Tasks was waaaaay bigger). I've ported several of my projects over, most of them taking less than 4 hours (I've got a bunch of 5-15k apps). Porting the Navigation code to 0.19 was done within one hour (depends on your implementation of course).

I wasn't around for Signals, and I bet that was a much larger breaking change. :)

Our largest SPA is about 44k lines of Elm code, and we have about 130k lines of Elm code across all our apps. At some point navigation was in pretty bad shape on the big one. So those were my best guesses.

I just wanted to let you know that a possible alternative to React/Redux that would be far more FP oriented is Mithril/Meiosis

mithril.js.org - vdom lib - for the V
meiosis.js.org - state pattern in conjunction with streams to give you the M/U

Check out the gitter chatrooms, the communities for both are very FP oriented, and working on making it easier to do FP all the time.

this guy came from elm: github.com/pakx/the-mithril-diarie...


Props to the OP, I would not have kept my cool replying to all these comments. Despite the disagreement of some of the replies, they seem to embody the described behaviour 😞 Eg not a single reply about how they are trying to listen to the users, just more "no, you're wrong, shush"


I am so thankful to Kasey for helping me avoid investment into eventual disappointment.

I started Elm over the weekend and was already singing its praise to my colleagues seeing how easy and quick it was to be productive in it. I am not interested in being a part of this community or this technology that wants to treat users as infants incapable of deciding for themselves. Everything Kasey said about the Elm contributors is in full display on this single post.

Elm is not the only fish in the pond. Thanks but no thanks.


I like the way Evan is designing Elm. His focus on the usability of the language is really great.

I do agree on the point about how the forum is managed. The first post on the (stealthy) release of 0.19 (*) was directly locked. That is ridiculous. Give the community space to talk about it, and don't force everyone to use slack.

(*) discourse.elm-lang.org/t/elm-0-19-...


"it seems likely that somebody will draw similar conclusions to us and be in a place where they want to create one"

My experience with Elm and the community mirrors this. We had to make a critical decision on how to move forward as well, and as an internal experiment, I decided to port Elm to Bucklescript. After using it internally for the past few months, I don't think we'll go back. The development experience is arguably better than we experienced using Elm. No more ports, amazing FFI, write your own effect managers, and write end to end Ocaml, with no need to drop down to javascript.


So what kind of toolchain or project templates are you using for Bucklescript? I really liked Create Elm App as a starter.


I find when I'm coding in Bucklescript my toolchain is pretty slim. Bucklescript, npm, rollup.js and postcss... and a testing server :P

Ah, I completely missed that you ported Elm to Bucklescript. That's pretty cool. Do you have it anywhere to look at, or is in internal? If you can't share it, do you have any place describing it? I previously checked out the Fable-Elmish source code, and MVU does appear to be a fairly straightforward pattern to implement. Integrations seem like the hard part.

There is also the bucklescript-tea library for an elm style library on bucklescript.


I posted this to the elm sub reddit to start some discussion. I didn't even realize there was a commenting section at the bottom of your blog.


The post had, in my opinion, some good discussion going. But it was then abruptly locked and removed from the front page. This just feels weird to me.


I'm glad "u/elm_mods" got a chance to vent. :) For the record, I was never banned from any forum. I don't even have Reddit or Elm Discourse accounts -- nothing to ban.

I think Evan is a rare one that can create amazing things. He certainly far exceeded what I could manage. Elm proves all that. But no one is good at everything, and creating a healthy community is hard and a completely different kind of skill. I could do no better there either, but I recognize when it's off. At least, closing your ears to the reality of the problems that users face, and insisting on idealism is not a winning strategy.

I have no malice in my heart. Since we discovered all the 0.19 changes, our team has been genuinely depressed about it, because we love coding UIs in Elm. I figured I could say nothing and quietly slip away. Or I could share my feedback as clinically as I could here (I'm pretty sure it would be suppressed in Elm's forums.) Maybe I would be heard. Maybe not.

I think Elm is one of the best products I've run across, and I hope all the spoils of success come to its contributors. I pointed out some issues, but I am rooting for Elm to overcome and succeed.


Haha, I want to stop spending time on this, but it is just triggering too much to not respond.

The post from u/elm_mods says:

There are good reasons why this feature request has not been accepted,

Then it links to this issue github.com/elm/compiler/issues/1039

So I spend a LOT of time trying out how to achieve TC-like behaviour in Elm. It is entirely impossible. And that issue does not actually explain any of those "Good Reasons".

being requested again and again.

Maybe people have a good reason for needing this? Maybe they are not just writing a Super Mario clone... ? Evan does not want to hear this. I have seen several issues where submitters spend a lot of effort explaining what they are doing; and eventually the issue is locked or closed and submitter is sent to another language.

Ironically and infuriatingly, one cannot comment on any of these issue, as they are both locked.

THAT is the issue with Elm.


Also it just occurred to me. The mod's post mentioned abuse. Viewing disagreement as abuse is pretty interesting to think about. For example, the kinds of effects that would have on forum interactions.


did you have a look at PureScript?

Where Elm takes you by the hand and steers you on a rather strict track PureScript gives you a powerful tool and maybe a bit too much freedom ;)

It's not where Elm is yet (things get's brocken on new versions and it takes longer for the packages to get updated) but I'm really hoping that we will use PureScript over Elm in production once it stabilized a bit more.


Thanks for the suggestion! I haven't looked deeply at PureScript. Although it sounds like a scary place right now. :) I also don't get as much into the Haskell-y stuff like HKTs and so forth. But I will check it out!


My original plan for An Outsider's Guide to Statically Typed Functional Programming was to transition from Elm to PureScript. The free sample of the current draft has most of the PureScript text. I motivate type classes in a couple of the Elm chapters (also included), which I think makes them less imposing.

Spork seemed to me the best PureScript implementation of The Elm Architecture.

However, I'd only put PureScript into production if I had people with Haskell experience and a good amount of time to become contributors. The community is friendly to beginners, but there's a vast amount of background that isn't explained in a systematic way, and the community standards for documentation and infrastructure just aren't up to the level we've come to expect from systems like Elm or Elixir or even Clojure. This is not seen by the opinion leaders as a problem - I hope it eventually will - but it makes PureScript something best suited for technology enthusiasts or visionaries.

That leaves me without a second half of the book. I will probably continue to work on it because things like type classes and effects are intellectually interesting. But my original hope - learning it well by describing it well, then using it for real work - isn't going to come to pass. I'm thinking of trying ReasonML from the F#/OCaml line of hybrid FP tools. I think it would be an easier transition from Elm than PureScript would be.

Disclaimer: I was too strident in claiming that PureScript needs documentation and infrastructure up to the modern standard. Many PureScript people think I'm a jerk and also biased. I don't think so (at least about the bias), but they could be right.

Agreed with the Purescript documentation, I takes a long time to become at home in that. Lot's of stuff is folklore and/or Haskell derived knowledge.

Still less frustrating than Elm.

Regarding ReasonML: it is like the saner brother of Elm, with a normal type system and mature tooling behaviour; in this way it's easier and better than Purescript, IMHO.

Both are highly recommended. FWIW, we are moving our code away from Elm to Purescript, Haskell, Idris and ReasonML.


It's really not that bad/complicated to learn (HKT's and PureScript) - but you gain some incredible cool powers ;)

To give you a small glimpse: if you understand what comparable is about in Elm you basically understood type-classes. But instead of have a fixed set of them that only works with a predefined subset you can add you own types to them (it's called making your type an instance of it) and you can even define your own type-classes if you want, but that is rarely needed.

If you understood what Cmd is about you are ready to talk about effect system - but again you can do it on a level where you are in more control of the runtime and where you are allowed to use effects (still everything is pure).

If you want to try it out this might be a good start: github.com/utkarshkukreti/purescri...

this framework is very Elm-inspired and you should get a good idea (normally I would advise PUX but right now the documentation was not updated for purescript-0.12 and so this might confuse you too much)


I find the title a little clickbaity (better title would probably be something like 'wyh we disagree with Elm's governance model') but I couldn't agree more.

Being new to the language, this is still something that bothers me and confuses me quite a bit. Especially how it is accepted and cherished for the core user base.


Apologies. I didn't mean for the title to be click-bait. It was an attempt at word play. Meant to convey that 0.19 didn't break our code as much as it broke "us" - the spirit of our team.


Elm is the product of Evan. It is Open Source, yes.

But it's still his product. :)

When apple decided to remove CD players from their laptops, they just did.

Community contribution and even usage of the "Elm product" has no strings attached.

I think this is better in the long run. It's better for Elm to have ownership (Evan).

When too many people decide on product features, we get Outlook like products.

This doesn't mean you cannot express your opinion about things. But they're just that, opinions and discussions.


Analogies are only worth so much, but please note that Apple still sells optical drives. They didn't leave the optical market out in the cold. Another example: Apple stubbornly refused to accept right click as a mouse feature for many years, because a single click was more elegant, and their elegant design did not "need" right click. Totally their call as it's their product. But people just used other mice or means of right-click until they came around to what the market wanted.


This doesn't mean you cannot express your opinion about things.

It means exactly that on Elm’s forums, which is symptomatic of what I tried to convey in the post. (I did not post on reddit, link was shared by another.)

Otherwise what you said is on point. It will also be better for us to have less risk with unstable decisions. But we like Elm so much, that this is all very unfortunate.


I think Evan's goals and rationale can be better understood here as he explains how we can define success for the elm language.


I think this talk may help provide some insight into the motivation for most of Elm changes.


Thanks for the comment Ashish. I did watch that video. I understand and agree with the vision for Elm -- Evan has created a beautiful vision. But how the vision is executed matters. It affects morale (both contributors and users) when "social shortcuts" are used to make the vision happen sooner. Shortcuts like not listening to feedback to the point of suppressing disagreement. Or insisting on idealistic choices for a future vision that don't address the practical reality of today. I don't want to use "native" code, for example, and I have used it as sparingly as possible. But until we get to the future where everything is available within Elm, it is the most practical option for some cases.

The post is not really about the specific choices, but about the signals that these choices are sending. Previously, I could (and did) just to isolate myself from the issues I mentioned by ceasing to participate in the community. But these last round of choices now affect my team's work. We can overcome these today, but based on the existing pattern, who knows what could be next?

I honestly hope that these issues will be addressed and Elm will come through stronger for it. But my current risk management strategy cannot be to hope.


I understand your dissatisfaction with the communication,I think forum posts lose a lot of intent but I'm not sure of the specifics.

I would also like to inquire if you have tried the port solutions as an alternative or posted about your specific cases where you have determined that native is the best solution to the slack. There's a ton of motivation to not have native modules with regards to the future and current optimization in addition to some other benefits. It is a definite trade off though. If you're looking for a more traditional FFI but less safe solution, I recommend you check out the ReasonML project.

We currently have only one case where native is the most practical way to accomplish what we need. You can read the full discussion of that with Robin here. Other use cases were mentioned in the linked reddit thread, and more could be found in other searches.

Regarding optimization, native modules are still usable by Elm package contributors, and are also subject to optimization. So I doubt optimization is a blocker to using them.

I don't have a problem with removing native access. But the timing was when the API is still known to be missing important cases. And Evan's post about it reads like a punitive decision. Between this and the community issues (which have the same root cause), the risk for us in using Elm has gone up.


I'm keenly enamored with F#. I played with Elm a while back (0.15?), and liked what I saw.

You have my sympathies with your frustration with Elm.

I consider Elm an very promising language... which is undergoing a LOT of churn as it finds its way. Each dot-release of this language makes dramatic changes. Ostensibly for the better, but trying to uplift a project from dot-release to dot-release can be an ordeal.

I'm not an early adopter. I used to be, but that was a long time ago for me. I'm a "1.0" adopter.

Or for Apple's Swift, a "3.0" adopter because what Apple called "Swift 1.0" should have been "early alpha", and what they called "Swift 2.0" should have been called "beta".

Anyway, I hope that Elm blossoms into something wonderful when they hit 1.0. And it won't be a Swift 1.0, I expect it'll be a solid 1.0.


Interesting post about community behavior.

With regards to "it takes discipline to write pure functions", having done FP for long time in Java (since v1.5), I think the discipline is worthy cos' it helps adopt FP mindset and practice FP independent of language support.


I liked your article, sorry to hear about your difficulties.

I also loved elm, but switched away because of exactly the issues you mention: native calls not being supported. I'm a person who wants to experiment and monkey patch, and while I got a solution using ports working it was extremely painful.

So I switched... to rust. github.com/vitiral/artifact is my project and it has both the front and back end written in rust+yew, which allows sharing of types and (eventually...) extremely high performance.

Is rust webdev ready for production use yet? ... probably not. WASM itself (which you should probably be compiling for) is only supported on the latest browsers -- and I'm sure there are lots of features missing. But if you were using Elm before, you might like rust+yew.


I really appreciate you sharing your experiences, feelings, and continuing the discussing in the comments.

In a way, it does appeal to me to have an efficient way to close out issues that are redundant, given that a link to the existing issue is given and the original user is given a friendly (could be canned) message explaining the duplication, and to redirect the conversation - but affirm they were heard. This could be worded like:

Hi! Thanks for posting on < <insert place here> > - it seems that you are asking a question someone else has already asked before, so here's the link to the existing conversation - if you can't find your answer there, please comment there and we can keep the party going! Feel free to DM one of the mods (here - < <list of mods> >) if you feel this is not a duplicate issue.

As long as it isn't just marked as a dupe like SO posts >.> - It seems like evan is inerested in redirection over closing - although those examples are just redirecting the "help me with X" type of questions to the discourse.

I'm going to speculate a little here, but one of things I hear a lot from my peers (18-30 age range) is this idea of emotional and social currency. That it can be draining to engage with people who disagree with them, and even more so if it is a harsh disagreement.

I think my peers have taken this to justify convenient disengagement. It's a trend that I see happening a lot in establishing small echo chambers that results in a community that can turn nasty fast.

This is very disheartening to me. I understand differing energy levels, and how social anxiety can play into that, but if people aren't exposing themselves to new ideas and people that make them uncomfortable, that is a bad thing.

I'm not saying that there are not times to disengage, but I'd rather err on the side of letting people talk too much than closing and locking too much. It's definitely a line/spectrum deal.


I agree with everything you mentioned. It seems harmless to me to let people vent a little. Even if it is just misunderstanding how to use the tools and you've heard it 1000 times and you just link them to another thread. Because sometimes people have legitimate issues. But you will never know if you just shut them down because they mentioned some keyword like "native". I don't often do this, but storytime. (Skip the next paragraph if you don't feel like a story.)

I used to play a game called EverQuest2. The mods on the EQ2 official forums were known to be heavy handed. One example was people requesting the Beastlord class which was a favorite in EQ1. They got so tired of redirecting and eventually locking posts which requested this class that they added it to the banned word filter. Eventually they even started banning people for referencing it at all. The community was essentially being told 1) "shut up" and 2) "we don't care." Because the community's voice was squelched (in general, not just about that), another site rose to prominence called EQ2Flames. Except it was like the darkest corners of reddit (before reddit existed). Yet, it was the only place players could go to speak freely (just before being ridiculed). Eventually, the official forums were mostly dead, and even the game devs had EQ2Flames accounts. (And eventually they even added the beastlord to the game.) But in the mean time it was a lot of unnecessary drama and stress on everyone. And for what? To enforce arbitrary rules?

I think we get so focused on marching orders (actual or perceived) that sometimes we don't consider how our actions play out in the bigger-picture human context. This Sandi Metz video really opened my eyes to some interesting things in that regard. One of the experiments she mentions was also the subject of a 2015 movie called Experimenter. It is also a fascinating watch.


Very interesting post about how the Elm community works and how it is organized, thanks a lot.

I don't have much experience with Elm itself but I do know Fable-Elmish, so before switching please consider the following differences (and also consider that my experience is based on Fable 1.x, but Fable 2 is already in beta, although I don't know if Fable-Elmish changed).

Elm subscriptions are based on the current model and are described as data, which means they are equatable and Elm knows when a subscription changed. In Fable-Elmish it is logic, i.e. a subscription has the signature (msg -> unit) -> unit, i.e. a function that gets a dispatcher and returns nothing. So Fable-Elmish can't know when a subscription changed and I assume that's the reason the subscription is only generated once, i.e. on init. So in Fable-Elmish you can't setup subscription based on your changing model, because you'll only ever get the initial model when setting up subscriptions.

Fable-Elmish is based on React. I'm not familiar with React and I find it a bit hard to write the glue code to be able to use existing React components from Fable-Elmish, but your mileage may vary.

Interacting with JS libraries is very easy and almost a joy with Fable-Elmish, but sometimes I get a bit lazy and I do a lot of dynamic typing. I don't think you can get that lazy in Elm, which I consider being an advantage of Elm.


Apparently since Elm forums have moved to Discourse

That means that users with a secure browser (= one without JS) can't even register there? Well, if they want that ...


Um, you want to discuss a compile-to-JS language, and you don't want to turn on JavaScript? Good luck with that πŸ˜‰


This is not a contradiction. I don't write every piece of software just for myself.


Switch to PureScript!
It has type classes, elastic developer community, support for Node, and many other non-browser platforms!


I've ordered a book (the most freshest, released on 22th. August 2018). But now it's not actual at all. Very sad.


You summed up how I feel - I moved to Mint - mint-lang.com


I made a typo. The correct acronym is SSCCE. Meaning Short, Self-Contained, Correct Example.


"the real kicker is that native modules are still there. They are just reserved for a few Elm contributors only. "

I think the sentence above is not a fair description of the current situation: is not that one from the core team can create his/her own package containing native stuff and publish it, while we can't. They also can't.

Native code is just for developing Elm itself, not its ecosystem. If one day you'll send a PR for a bugfix in the core/String module, you'll probably write some native code and it could be ok.


The comparison to using native in core I feel is quite a fair one. If native is so egregious, why don't the core packages also use ports? Elm's design could totally include a system port, and it could use an API like what Elm users are told to use. (Send Value out of the port and decode its operation and data in JS, and likewise when it comes back into Elm.) Then, aside from what needs to be compiled in Haskell, core packages would not have to use the evil native code either. Win-win, right?

No. The reason is because such a thing is impractical for many core use cases, even if possible. And being that Elm's existing API doesn't even come close to covering all web capabilities, some of the ones that we ordinary Elm users face in our apps are also impractical to do over ports. I've seen several use cases mentioned, such as web sockets, or using popular JS libraries which do not work well with the asynchronous nature of ports. But I'll give my specific use case as an example. The next paragraph is mostly copied from another thread under this post.

The primary thing Elm fails to do for us right now is type-based JSON de/serialization. Elm's built-in encoding and decoding is great for fuzzy APIs. However, that is not a situation we find ourselves in. In 99+% of our internal API types, the server and client types line up exactly 1-to-1. (There is only 1 case where we need to use a decoder.) We adjust these types regularly as we implement new or update existing features. So for us, using encoders and decoders creates hundreds of lines of redundant/difficult code that we have to touch regularly. So maintaining co/decs has only downsides, and there is no non-native way to handle this in Elm. Instead, we define a port (never used), and call the 20 lines of referentially transparent native code to extract the auto-generated encoder or decoder from the port.

My case may be different from most other users, so I don't expect Elm to have this feature right now. Nor a lot of others that people might need. But I would generally expect users are able to reasonably cover their needs. And for that reason native usage in app code compares fairly to native in core code... because in both, it is otherwise impractical (even if still possible) to accomplish some use cases without it. At least for now.

Its eventual removal seems like a good idea. But its removal at this time seems whimsical or even punitive based on Evan's post. This kind of decision raises the risk meter for us on using Elm going forward. Because now we're wondering how much more divergent from today's practical realities subsequent releases will get.


I agree that elm core developers have good intentions, but too often too strict.
I had a similar experience with elm format and cookie support.


Thank you for sharing your experience. I am curious if you have anything to add to this after a few months, or if this is also your current assessment. Thank you!


Thanks for the comment. I haven't been following Elm news so I don't know if there have been any recent developments. However, I did watch Evan's recent video on the hard parts of open source. It reinforces my assessment that there is a top-down authoritarian perspective on managing the community, and it isn't the place for us.

Analysis of the video: Evan brings up Orwell's 1984 as cultural shift to a distrust of authority. The context of his talk seems to imply that mistrusting authority is part of the problem. The communication patterns he brings up at the end are very controlling of the end user, ostensibly for the good of the community. This makes the intention seem deeper than just controlling the destiny of the Elm product. It means also controlling a collectivism-based Elm community using authoritarian strategies. This agrees with my own experiences and observations. For me, this is a bit too intense of a requirement from a technology.

I have started a project in F# using Fable-Elmish libraries, and it is equivalent (and syntactically similar) to Elm but with a lot more freedoms. In fact I can go a step further now and test that the update function produces not only the correct model, but also the correct declared effects. TBH we don't do unit testing of Elm UIs, because we haven't had the need. But I appreciate being able to declare my own effects and write their implementations in F# off in its own corner, rather than having to go across ports and switch to JS. Also auto-JSON decoders.