Reasons that people were forced to move from Elm to something else?

Hey thanks for the reply. Yeah I noticed in my original message I didnt go into any of that. I do mostly feel like Elm wasnt presenting any technical barriers to our development. I dont want to be unfair to the folks at the company who didnt like Elm, who probably did feel that Elm presented blocking technical problems. So let me try and list out some tense technical topics that maybe approximate what the other side felt was a blocking technical problem.

Api Tokens

Our Elm projects used a lot of ports for http requests. This is because our company already had a strong frontend JS api project that was re-used everywhere for these kinds of requests. One day we tried to do all the http for an Elm project wtihin Elm, just to see how it would go. We quickly ran into problems with how to store and refresh an api token in the Elm model. No one had a really good idea on how to do that in our existing set up. I remember that being an embarrassing day for the pro-Elm side of the discussion because others felt it should be trivial.

This is a non-problem for me now, simply because I now know how to do this well in Elm. We really were on the bleeding edge of Elm development, and I dont think good examples even existed online. I think the competing JS implementation for how to do the API token stuff relied on mutable JS objects, which, I guess would indeed make the problem a breeze, at a big sacrifice to our stability. I remember some of us were looking towards Haskell for inspiration, and I think the leading example relied on typeclasses and very effect-ful and IO heavy operations.

Reusable view components

At least in my project, I feel like we suffered a lot of “similar is different than same” problems regarding our UI components. Two spots in the UI would look very similar but had subtle differences, that would tempt me to make a re-usable component. But, the subtle differences masked the code complexity involved in making one common reusable component, and that complexity was great enough to undermine the point of reusable components altogether. So, personally my solution was writing a lot of duplicate code manually. The amount of duplicate code I was writing might not have impressed the Elm-skeptics in the company.

Just like the previous point, this just is not a problem for me anymore. It took time, but I and seemingly the Elm community as a whole gradually learned good ways of making code re-usable in Elm. In some ways this is not even an Elm specific problem. The way I think about reusability now is not an Elm specific domain. Its just a nut you have to crack in every language and I could have gotten it wrong in React too.

0.19 Navigation

As the 0.19 release approached, I think we knew the api for url navigation in 0.19 was quite strict, and that in 0.19 you could only do url navigation if your Elm app had control over the whole page. Well, guess what! We had a lot of small Elm widgets that did navigation, so in order to migrate we would probably have to come up with our own solution that involved a lot of ports. I recall someone saying “Evan thinks we are stupid” in reflection on this, as in, Evan wrote an api to force us to take a certain approach, which implies he doesnt think we can make this choice ourselves.

It seems like the Elm-skeptics had a point, that Evan did in fact add difficulty to our ability to upgrade. Whether or not this additional difficulty on our end was justified in the grand scheme of things, or whether or not it was a good design to begin with, are two questions I just dont know the answer to. But, either way, the whole topic was not relevant in any practical way: we were not at the moment trying to upgrade to 0.19; we didnt necessarily even need to upgrade to 0.19, 0.18 was doing great; and the upgrade path we did have to 0.19 was not in fact overwhelmingly difficult. So, in my view, which sides of the discussion were right had little relevance to writing Elm code; but it was probably taken as a sign that Elm is going to create big problems for us anyway.

9 Likes

Totally with Chad again on this.

While I do believe Elm solved a lot more technical problems than it presented compared to alternatives such as React, I do think Elm comes with its share of organizational, communication problems. I believe is a thing that makes Elm really hard to sell to even open-minded sceptics:

That thing is: Why are there issues and PRs open for years that involve bug fixes? I think they should be closed or worked on. I don’t mind not getting new features but I do think releasing bug fixes in an appropriate amount of time is critical for credibility.

I love Elm and have taught Elm to at least ten people, but this one is really hard to defend IMO.

16 Likes

I come back to Elm every so often just to see if it’s still around. I see the last release was a year ago now, and that brings me to the issue I had convincing my co-worker to look at it. How do you convince someone to seriously consider a project that is not at 1.00 at least and seems to be moribund release wise? I realize that neither of these are the case but to the outsider it sure seems like it.

2 Likes

Eh, why would you release a new version of the compiler if the old one is still working fine? Much of the action is in the libraries.

It’s a communication issue: the version number implies that the language is not stable (or it would be at 1.x), so people expect things to be changing. But since there doesn’t appear to be a lot of change going on (either in the form of releases or blog posts), it’s easy to assume that the language must be stagnating. You can explain how things work in Elm land of course, but first impressions are still important.

3 Likes

This doesn’t mean anything. React Native is 0.63 and is production ready for years, lots and lots of companies use in production. And having less releases is a desirable thing, the correct name is stability, big companies need it. Evan still works full time on the project.

6 Likes

Long-open bugfix PRs are another reason for this perception

5 Likes

React Native is 0.63 and is production ready for years

That’s definitely an outlier / exception to the rule … First of all, React Native is developed, financially backed, promoted and heavily used by massive companies. Secondly, there’s the great branding associated with React that React Native piggy backs on. Sure, React Native is not yet in 1.0, but React is and has been for a long time.


Follow-up / edit: My point is, by having a 0.x.y version, you’re already raising eyebrows for folks who may not be fully aware of the language / library / ecosystem. So it’s already an up-hill battle at that point.

3 Likes

why would you release a new version of the compiler if the old one is still working fine? Much of the action is in the libraries.

Perhaps for optics. To help sway management and ease concern of skeptical colleagues. And to signal to people that “this compiler is indeed quite stable and has been used in production by several folks”.

2 Likes

React was already widely adopted on version 0.14. Then, they decided to strip the 0 and the next version became 15, but in fact it should have been 0.15, and the current one should be 0.17. Or maybe it should have been called 1.0.0, but being on 1.0.0 also feels immature, so they skipped 14 numbers. Browsers used to release new major versions every few years. Then, chrome decided that everything should be a major version. Now, i f you are in version 1.0.0 you look in early stages compared to chrome. Instead of playing around numbers, check the ecosystem. JavaScript has been there since last century and still has a messy ecosystem pushed forward by hypes that last after a few months.

Also, nowadays, with continuous integration, it is common to promote releases, not create new ones. So 1.2.0-alpha becomes 1.2.0-beta and, afterwards, 1.2.0-stable, but they are exactly the same thing only with different tagging.

So, Chrome could be at version 3.7, React could be at version 1.2, and Elm could be 2.1. The number is irrelevant, the important thing is what they offer.

1 Like

Could you elaborate on that? What is the main advantage of React here? One of the more obvious advantages of Elm seems to be the ability to create reusable elements with extreme flexibility. Is the problem that you need to use Html.map and Cmd.map and hook up everything to the app’s main update function?

2 Likes

I’m not saying React is better for UI, in fact I am convinced Elm’s guarantees are much more desirable than the alternatives.

What I wanted to say though was that:

  • React is very easy to grasp mentally and sell to a team of developers, because a “component” is a seemingly simple concept and every component has the same, simple pattern. It’s easy to understand and get right into it. Of course in the long-term local state is something you end up wanting to avoid. But the point stands.
  • It is difficult in Elm to know the right pattern for something in the UI. There are many questions one has to deal with. Should we try to emulate Evan’s SortableTable or should it just be a view function? or should it be a collection of functions and a model and update? And even if you sort out a good pattern it doesn’t mean it applies to the next piece of UI, every new “chunk” of UI is something of its own, and it most likely differs from app to app. After all this, then one has to care for, as you say, hook everything up (as opposed to just one line in React).

I know the reasons for why this is the case, and am sure React hides a lot of the complexity at the cost of many other issues which will eventually show up. I am confident Elm is a much more solid option for modelling UI.

But as a matter of “why people move away from Elm” I think the Elm community should not underestimate how seemingly unnecessarily complex Elm appears as opposed to React components and one-line examples. So many times did I encounter rolling eyes and “why does it need to be this complicated? in react it’s just …”.

Also, even if one has an optimistic attitude towards learning Elm it is discouraging to find little help in learning how to think about UI “chunks” (to avoid the dreaded “component” term). Maybe UI chunks should not even be a special thing in Elm, but it is obvious that most people coming from JS still ask the question.

I think a series of something like elm patterns or elm css patterns for different common patterns for structuring UI “chunks” would go a long way. If nothing else, we should help convinced elm developers to communicate what would a UI library look in Elm.

UPDATE: should leave this great resource here as well https://package.elm-lang.org/packages/NoRedInk/noredink-ui/12.8.0/

14 Likes

No, they skipped numbers to simplify versioning of community libraries. We can joke about javascript and its pace but Facebook recognised weight of their ecosystem and community there.

Number is relevant. Elm couldn’t be 2.1, because Elm had far more breaking changes than 2.

The problem with Elm not being 1.0 or more is that by convention we should expect more breaking changes out of nowhere. This is a signal that Elm is in design phase and core team is focused on creating Elm as perfect language and not maintaining it as developers tool.

1 Like

I think one of the hard parts about “components” in Elm is that there is (at least) one thing in the standard library that acts as a component: Namely the plain old text input. It does keep its own state, namely the text and current cursor/selection. If you want to do something more sophisticated with it, you will probably make the text explicit (and sometimes run into trouble because you can’t do the same for the cursor and selection). But if you try to model your own interface elements after the text input, you quickly notice that you can’t do that because most interface elements have additional state (like the cursor) but you cannot save them in the component (except maybe using WebComponent trickery).

So you will have to learn how to thread the state of your interface through your application which is hard because you never had to do it for the basic interface elements.

(I think a real solution would be to make the state of all components explicit, even the cursor/selection of basic text boxes, and then find a nice and understandable way of composing these states. Then you would learn how the composition works with the basic components and designing your own “components” would become easier because you wouldn’t need to figure out writing and using components at the same time.)

3 Likes

I think this is true, its a petty thing but the number does matter. Elm should bump to 1.0.0 or perhaps 19.1 in my view.

It was announced here that Elm is unlikely to change in any significant way for maybe 2 or 3 years:

Which is awesome from a quality and stability perspective. Not so good if you are hanging on for a bug fix.

To give an example, we created a PR for a stack overflow problem in the time-travel debugger. Should take 10 minutes to review and merge in, its just the minimal set of changes needed to make a certain function tail recursive. When your PR doesn’t get merged in, you don’t bother to make the next one.

12 Likes

The old debois/elm-mdl package had a way of associating state with UI components. Basically, each component that needed state had an ID assigned to it, and the component state was kept in a Dict that you needed to thread into the Mdl update and view functions.

Threading the state was easy, you just kept it in your Model and passed it in where needed, and put any new value returned to you back in your Model.

Assigning the IDs was harder, because you had to do it manually. The reason is that there was no way to thread component creation, and have an ID generator embedded within that. The IDs were List Int, which was helpful in the sense that you could number some major part of your UI as say [1], and then some control within that as [1,1] and so on, and more easily avoid ID clashes and re-numberings that way.

I can see a lot of people would balk at that, I didn’t think it was so bad myself.

===

I thought about whether it might be possible to thread an ID creator. Suppose we just use an Int and try to thread that through component creation:

type alias IdGenerator = Int

someComponent : IdGenerator -> (Html Msg, IdGenerator)

and each component would just bump the ID by 1, and return the new generator. Asside from the fact that this does not make your code nicer, the problem with this is, each time you change the DOM to add/remove components, the numbering will change, and existing components will get the wrong state.

===

Is a nicer solution within a pure functional language even possible?

I enjoyed Richard’s Elm Europe talk on Scaling Elm a lot, and he does explain that the problem comes from trying to think in an OO way. We can make an attempt at emulating the OO way of doing it but with drawbacks, or we can do it in a way that is more natural to Elm but that does not give us component libraries.

In my view, at some point it becomes inevitable that you need >1 re-usable UI chunks that need to track some state, and I did not mind the manual IDs as per elm-mdl so badly, so it is a technique that I am prepared to use but in as few places as possible. I think using IDs and a Dict is better than having to explicitly store the individual model for each component in your application Model.

Here is a link to the relevant part of Richard’s talk, comparing the OO way of doing things with Elm: https://youtu.be/DoA4Txr4GUs?t=3295

1 Like

This is especially poignant when you remember that packages are forced to follow semver, and that packages can’t be released as version 0.

Evan understands semver and the impact versioning has on stability and trust, he’s said elm won’t change much fundamentally in 0.20 so let’s just do away with the 0 and communicate to the wider community that Elm is stable and ready to be used.

The whole “0.18 -> 0.19 apocalypse” thing wouldn’t carry so much weight if there wasn’t the looming threat of it happening again.

4 Likes

Great post.

Yeah, it does feel like there are a lot of questions to do deal with. I never found it a burden personally, but I do feel like I have accumulated a very large tool box of different patterns to work with in Elm for UI components. Its not easy to communicate this big toolbox the others, like “Just make a component” is easy to communicate. Usually the best I can do is pair with someone, and face a specific UI task, and then mock up the various alternatives to whoever I am trying to communicate with.

And I also 100% agree that if you dont grapple with all these questions, then you are just hiding problems. They are real problems that belong to the domain of browsers whether you are using React or Elm or any other technology.

I feel strongly that SortableTable should not be what anyone uses.

1 Like

Regarding the API tokens, that needs to be refreshed, I’m just curious about your solution to this problem. We had to implement the feature with token being refreshed after some time and we ended up with JS handling this part of checking and keeping the token fresh and sending the new one through the port to Elm.

I use a wrapper function that fetches the new token and ‘repeats’ the original request that failed due to the token being out of date. I’ll open a topic here for it at some stage.

3 Likes