back
158 comments
> Languages like Go and Elm spurn extravagance. They resist overcomplication. They force me to solve real problems instead of fighting compiler errors and stylistic differences.

I hate this mindset. "<my favorite language> is used to solve REAL problems, other languages are not as good for creating VALUE. Any powerful language features, ergonomic syntactical sugar or tooling that does not exist in <my favorite language> is useless". So strange

I think you're just reading it as "Elm/Go good, $yourFavLang bad".

Maybe this makes more sense:

Coming from more expressive languages, one of the good things I could say about Go's developer UX is that you are so helpless to circlejerk over abstractions that there is simply nothing else to do than to write concrete code to solve the problem.

Elm is similar versus the huge type expressive power of Haskell. Elm's type system is so minimal compared to similar languages that you can't spend hours perfecting your higher kinded advanced type abstraction that perfectly annotates and cordons off the problem domain because there isn't enough typing power to do that. You have to go "welp, good enough" and move on.

I'm gonna take a bit of a "people-pleaser" stance on this and say that there's merit in both mindsets.

Personally, I tend to prefer using and abusing all the sugar and tools that a compiler gives me. I find that I'm not a terribly smart person most of the time, and if a compiler engineer has a figured out a good bit of abstraction to make the code safer or more readable or faster, I'm inclined to use it.

There are plenty of success stories with this approach. Love it or hate it, I think SQL is overall a reasonably pleasant language, and almost completely removed from the underlying hardware. You think relationally with SQL, not really in terms of for loops or memory allocation.

All that being said, I will admit that sometimes I don't want to spend the entire day trying to decipher whatever the hell GHC is trying to tell me with its weird errors. Go makes you do a lot more manually, but at the same time you also don't need to understand the intricacies of a sort of approximation of type theory or linear logic.

IMO, I genuinely think that right now the two best languages in terms of abstraction usability are Clojure and F#. They both allow for lots of great abstract stuff, but they also do allow you to cheat when necessary, and being on the JVM and .NET Framework respectively, there's no shortage of libraries available.

It's something that you can fall into pretty easily imo, but after you dive into a few languages and realize you just weren't aware of the tool chains, librarys and platforms you begin to realize familiarity accounts for most of your enjoyment.

I like golang a lot and use it professionally and there are plenty of errors and issues that can require syntax and code that to people who aren't super proficient in it would think is over-complicated and end up fighting the compiler (channel can be awkwardly implemented and related issues and what not can be.... non-obvious..).

I've been writing a ton of rust recently and until I became proficient I felt it was really complicated and led me to fight with a compiler (borrow checker I suppose) and honestly it took me coming back to it a second time almost a year later to break through it and now i'm as productive in rust as I am in golang... but it was my familiarity, I found tools I wasn't aware of, my SQL query strings & templates are now checked statically and so I feel more productive in rust in some ways.

> <my favorite language> is used to solve REAL problems

That is really not the point being made. The point is rather "the language helps me keep focused on what I do, because many subtleties in other languages don't exist, and those have me overthinking things". Whether what you do is REAL work or a friday night game jam is irrelevant.

Also I wouldn't say that Elm lacks ergonomics or powerful expression features. It does lack browser API features, but I don't believe that's what the author enjoys.

I think there's a case to be made for simpler languages, but not the way the author portrays it here, and not the way eg Go does it.

IMO the biggest problems with almost all popular programming languages are

1) null

2) exception based error handling

such that, when you call foo() where foo is

String foo(){ blabla }

you can get a String, null OR an exception (!!!) and most compilers happily let you treat it as if it only ever returns a String.

I hope some day null is no longer a thing, and that Functional Programming types like Option, Either, Try etc in the native libraries is the new default.

incredibly, there's still no consensus as to which exceptions should be used for what and when, though these days the most common approach is to simply stick only to RuntimeExceptions, which is terrible.

Functional error handling using Option, Either, Try etc are arguably much simpler, safer and more powerful than exceptions.

Simpler because they don't rely on dedicated syntax- they're just regular objects no different to any other object.

Safer because unlike exceptions, they force callers to handle all potential outcomes, but no more. (no risk of ignoring errors and no risk of catching a higher level of error than desired, ubiquitous bugs in exception based error handling)

Powerful because they support map, flatmap, applicative etc, making it easy to eg chain multiple computations together in desired ways, which is unwieldy and bug prone when using exceptions.

It could be that, when learning Java, Python and any other language, we learn that methods return objects... and that's that. No weird dedicated syntax and magic, special treatment for returning anything other than the happy path, and the HUGE complexity that comes with it, eg the dedicated syntax itself and how it behaves, differences between checked and unchecked exceptions, hierarchies of exceptions etc etc.

In addition to that, when lists and booleans implement map, flatMap etc, you can actually reduce syntax of languages even further- there's no need for looping syntax like for, while etc, and no need for if else either. This is probably too extreme for most people, but think about it. There's literally no reason to have this syntax in the language if the types in the library give you the same functionality.

So my dream languages would be something like Kotlin ie with inferred type safety, immutability by default etc but without support for null at all, no exceptions at all, no looping or conditional syntax, and a better, smaller, simpler library.

As an application gets more complex what starts to matter is general design, software architecture, performance, compile times and language agnostic features.

Obsession with language features or syntax tends to move people towards building castles in the sky and being too obsessed with code rather than the software that actually runs on a physical machine. A lot of fancy features usually come at quite high runtime or compile time costs with not really meaningful benefits in a large software system.

Unless you're writing software explicitly for the sake of staring at code, unopinionated and simple, fast and pragmatic languages that get out of the way are the tool of choice for good reason.

Author here :)

I definitely don't think ergonomics and features from other languages are useless! I just feel a bit overwhelmed and distracted by variety sometimes, especially when working on teams.

For example, about 50% of the JS teams I've worked with collectively agreed not to create new classes. I think I'd prefer working with JS if there were only one way to do things, but it doesn't mean that classes are bad or useless.

It's a valid assessment depending on the context. There's a lot of software scaffolding that exists in places that, usually for good intentions, creates complexity in the hope of simplify the problem at hand. Sometimes it works, sometimes it doesn't. When it works, it's great. When it doesn't work, it adds yet another layer of complexity to deal with whatever problem you're trying to actually tackle.

Ultimately it comes down to trying to do a cost/benefit analysis of the complexity at hand and deciding if the additional layers add enough value and how far your problem deviates from the supporting structures. The issue is, it's often quite difficult to know a priori what is helpful and what just adds complexity because goals are often moving targets and you have to try and assess the range of potential goals with the flexibility of all the middle layers you introduce.

I read this as an expression of preference not a condemnation of other languages.

The full context helps

Most languages are too powerful for my palate.

Don’t get me wrong – I love Rust and many other languages! But sometimes they’re just too much for me.

When writing Rust or JS or Haskell or Python or Lisp, I’m overwhelmed by opportunity. Should I make this generic? Should I use classes or structs? Immutable or mutable? Macros? Functional or imperative array manipulation?

I try to please compilers and coworkers and customers, but all are disappointed. Give me a woodshop and I’m lost, but give me a simple chisel and I intuitively know what to do. There’s a certain freedom in restricted toolsets.

Languages like Go and Elm spurn extravagance. They resist overcomplication. They force me to solve real problems instead of fighting compiler errors and stylistic differences.

Furthermore, consistent code makes portable mental-models. Go and Elm codebases tend to be extremely readable.

Speaking as a dude who loves legacy Lisp - I once wrote an interpreter for it in Elm. I was disappointed to find there wasn't enough parenthesis in Elm! Sometimes the bell and whistles get in the way of my creativity and flow
I loved Elm as soon as I had a running app that I could refactor and be (reasonably) sure it would work once the compiler was satisfied.

However, I don't like the way the project is run. It's one Benevolent Dictator that has a particular vision for Elm and he's not really sharing with the community. For context, the latest Elm version (0.19.1) was released in October 2019. It kind of feels like a nice tree house left to the elements because the person grew out of interest, but kept a lock on the door.

Have there been any efforts to fork it?

0.19 also prohibited interaction with non-Elm code which I recall a controversy about. But can't seem to find out if anyone forked 0.18 because of that.

Indeed the releases are less frequent and Evan works in batches to avoid breaking changes every year. But he didn't left, he still works on private branches and on security patches when needed. Yesterday he gave this presentation:

https://gotoaarhus.com/2023/sessions/2529/elm-on-the-backend

Yeah, partially because of how the project is run I chose to go with elmish for my own project.
As a counterpoint to the inevitable "Is Elm dead?"[0] comments, how many other languages are still rock solid after 3+ years without a new version? Shouldn't we aspire towards using tools that are stable because they are complete?

What is the maintenance burden of the average React app? When I have written an Elm app, I feel confident that I could come back to it in a few years time with no issues.

To me, this stability is a testament to the language's thoughtful design and rejection of the constant churn of contemporary web development. At the risk of sounding like a Game of Thrones fan waiting for Winds of Winter, I look forward to the next version coming out with modest changes and bug fixes whenever it is ready.

[0]: https://iselmdead.info

That website justifies Elm's release cycle by saying that the language evolves slowly and that's a good thing, but you and they are conflating the bug fix release cycle with the feature release cycle.

I don't think people would be saying Elm is dead if there were regular bug fix patches coming out and we were on v0.19.21. The reason why people are declaring Elm dead isn't because new features haven't been added in two and a half years, it's because there hasn't been a bug fix update in two and a half years.

Sure, the language is stable in that it doesn't change, but stable can also mean bug-free, and Elm is certainly not stable enough to justify going that long without a single bug fix.

It's not rock-solid nor complete.

The authors refused to fix a parser error related to negative literals: https://github.com/elm/compiler/issues/1773

Looking at the number of opened bugs and lack of releases, I wouldn't call it rock solid.

https://github.com/elm/compiler/issues

If the low hanging bugs can't even be triaged, what hope is there for any future innovation? ie, the countless unsupported browser APIs

It is clear that Elm is understaffed, to say the least.

I still use Elm daily. Even if development on it is essentially paused for the foreseeable future, it is still much better than the alternatives for me.

For example, all Elm apps having the same architecture ("TEA") is one of the biggest wins over alternative apps where every project, even those you make yourself, will do things differently.

Elm Janitor (https://github.com/elm-janitor/apply-patches) is a curation and applicator of community patches to Elm proper. Haven't used it, but it seems like a promising way forward.

The fact that Elm had traction and popular support (books/youtube tutorials/etc) most language or framework projects would kill for and then basically dropped is almost criminal in my mind.
re famous Elm error messages. This one I got when I was learning Elm 4-5 years ago.

  Elm uses a different name for the “not equal” operator:
  
  5|   text "Hello!" != "balbla"
                     ^^
  Switch to (/=) instead.
  
  Note: Our (/=) operator is supposed to look like a real “not equal” sign (≠). I
  hope that history will remember (!=) as a weird and temporary choice.

Wondering if it is just me, or it really is passive-aggressive? It was the first red flag for me.

upd: formatting

its fairly direct. And not wrong.

Passive aggressive might be like this

"there are some languages that feel the need to use !=. They have the 'opinion' that this was a good idea, look at them. They are so cute trying to be a real language with such *interesting* design choices"

The note absolutely is, the use of `/=` is just consistent with Haskell though, which to me makes perfect sense.
I was also using it for these reasons up to about 10 months ago. I've switched to rescript now because it still addresses most of these, while being a lot closer to the mainstream of frontend programming.

Rescript does piggyback on normal JS ecosystem and build systems so comes out worse there. But it's easier to integrate with existing js codebases and npm packages for the same reason, and its output can be used from js in any framework if you plan for it.

I was really missing the elm command/update model for a while but at some point I realized adding that semantics to a react reducer with a custom hook was completely reasonable, and there are a couple existing projects doing exactly that. I wrote my own in an afternoon and have been copying it around to new projects since.

I'm like 90% happy with this transition now. It doesn't always feel quite as safe & magical as elm did, but it's also a lot easier to integrate with other systems.

Interesting, got any repos written in this style?
The contrarian HN view is below.

432 comments | 3-years ago

https://news.ycombinator.com/item?id=22821447

Elm has lots of great ideas, but if I were making decisions in a company, I wouldn't use it in production for anything big and long-living. Simply too much of a risk in terms of support, and finding developers with experience using it.

Only contacts I've had about Elm positions have been about rewriting existing Elm apps to something else.

It's a shame Elm was abandoned.

Impossible to justify for serious projects at this point.

Would you mind sharing a link / citation for this? Elm releases are intentionally long and the project appears to be ongoing [1].

[1]: https://iselmdead.info/

Edit: moved the position of the citation.

It had so much potential. PureScript is a good alternative with an active community and democratic development process.
The successor to Elm is probably “Elmish” for F#, which is a bit less opinionated. It can interop with any JS code so it’s a safer bet.
Is elm dead?
We also use Elm in 2023, just got the first project to production a few months ago and we absolutely love it. Finally a way to tame the complexity of browser-run-code.

We only use it when there is complexity: when there is just a little progressive enhancement needed on a SSR HTML page we happily use vanilla JS or jQuery (we're looking for a good TS-based jQuery-like solution the fits that bill).

What we like about Elm:

* makes us think about tech design issues early on (you cannot just ignore them)

* its a transformative experience: devs become better at writing any language after having solid Elm experience

* its fast to compile compared to TS+React+Redux+Babel+WebPack+...

* no unhandled runtime errors! (yes it is true, no more errors with Elm)

Just like I find Ruby a very nice language that was hidden in Perl, I see Elm as a very nice language that was hidden in Haskell. Thanks Evan for creating it.

And yes I truly believe Elm is not dead but merely finished to a great extend.

Oh, as a bonus, want to have your mind blown, check out this:

https://www.youtube.com/watch?v=nSrucNcwlA8&t=275s

(when I watch that video I cannot unhear "look at all the boiler plate im not writing" in David Heinemeier Hanson's high pitch voice; referring to the original Ruby on Rails demo)

> no unhandled runtime errors! (yes it is true, no more errors with Elm)

I used to work with elm some years ago and my coworkers claimed this as part of their reasoning for choosing elm. Shockingly, we still had runtime errors! Elm helps reduce some type system based runtime errors. But that’s only a subset of exceptions, and it’s not perfect at even catching those. Try this in elm:

div [ attribute "@style" "color: green" ]

It’ll compile just fine. And crash completely at runtime.

> And yes I truly believe Elm is not dead but merely finished to a great extend.

No less a CS personage than goddamned Donald Knuth uses the decimal expansions of irrational constants to denote that his programs approach "finished" with smaller and smaller changes. Somehow this is fine when he does it but "the language is basically cooked as far as syntax goes" is an unacceptable answer to the Elm decriers. Dogs bark; the caravan goes on. Mazel Tov on launching your thing in production. I wish you a thousand years of success.

Wait until you want to support an enterprise customer and you need to adapt their requirements in a quick way.

Elm is fine for learning, but that's all for me. Serious products for serious customers require more than "beautiful typings"

Aww, I was hoping this was about the email client.
If you want to use Elm for your hobby project, go for it. Everyone else, choose something that has a well established development team - the operative word being team. One-man development efforts (no matter their genius/brilliance) are too risky to depend on for serious work that needs to work/be-supported in 5+ years.
What I loved most about Elm was the syntax, types and it's incredible CLI . But I found the architecture and working with foreign data (JSON APIs) just too strict to be productive.
highly recommend the talks "making impossible states impossible" and "make data structures" by richard feldman.

https://www.youtube.com/watch?v=IcgmSRJHu_8

https://www.youtube.com/watch?v=x1FU3e0sT1I

the talks are geared towards elm but I think they offer some great advice applicable to programming in general.

Sometimes I dream about writing my own secret coding language that no one else knows so I can have this personal/private connection to the digital products I build. I would make all my code open source, but no one would understand it.

But that would take a lot of effort, so I just use Elm instead.

I can relate to most points in the article but definitely not #4. I'm a newbie and Elm's ways of declaring types are confusing to me. There are custom types, type aliases, records, extensible records, opaque types, phantom types, wrapper types [1]. However, I still wasn't [2] able to model a list of items with a common base type without having to switch-case through all possible types.

[1]: https://gist.github.com/JoelQ/6b303d9ad450537163b6f8f6cf8a4e... [2]: https://ellie-app.com/mQ52TY6k3zZa1

I thought this was going to be about the Elm email client. I guess I'm old af

I don't think I'd ever use "elegant" to describe Go

it's a workhorse language that's readable and full of utility.

When I think elegant, I think Clojure. Not that I'd want to use it day to day (I have)

Do you know of an up to date Elm course?
Has the Elm community finalised a canonical way to work with Elixir Phoenix?
elm seems to be a very opaque project; caution must be taken before adoption.

the architectural model is good, and there are many projects mimicking it in a more open way.