
Elm 0.19 Broke Us - maxhallinan
https://dev.to/kspeakman/elm-019-broke-us--khn
======
Tehnix
I think there’s a very weird mismatch between the way the core language people
are pushing for the adoption of the language, and then at the same time they
will turn around and say “we’ll, it’s not even 1.0, yet, so what’d you
expect”.

The way Elm is developed is fit for a language that has little to no users,
and can take going so long between updates, that remove escape hatches needed
to fill out the immaturity of the language.

It really saddens me to see it go like this, because I once had high hopes for
Elm. Nowadays I see it purely as a stepping-stone into more advanced languages
like PureScript and Haskell. Elm is there to hold your hand, but it seems it
has no intention of ever taking you further than the basics.

~~~
erokar
What you term the "immaturity of the language" is imo a well thought put focus
on simplicity. It was never Elm's intention to reach the complexity of Haskell
or indeed PureScript. I think that was a sound decision.

~~~
mikekchar
I think you are right, but the way decisions are communicated in Elm are
frustrating. There are lots of decisions like this, which in the end are just
decisions, but can be frustrating if you are expecting a more complex
language.

Even without talking about type classes, the lack of applicative is weird. I
know: nobody understands what applicative is for, but if you have map and you
are currying parameters, you're _going_ to run into the issue ;-) Instead,
you've got map, map2, map3, map4, map5 (which also, frustratingly, don't
implement applicative). There are lots of validation scenarios that are just
way more complex to do in Elm than they need to be.

But to be honest, it's fine because the language is not supposed to give you
everything that you might want. It's geared for people who want a subset
that's easy to learn. If I'm going to write code for myself in this space
(functional language that compiles down to JS), I'm going to pick Purescript
because it has everything that you're ever going to want. But if I'm choosing
a language for my team that doesn't know functional programming and (to be
blunt) doesn't really care to learn: Elm is a much better fit. They can learn
just enough to get their work done.

But I just wish it was stated in those terms clearly. The premise of the
article has been played out time and time again in the Elm community: "I
thought this was a fully featured functional language, but when I tried to do
this completely reasonable thing I got my hand slapped".

At every turn the response to, "Why can't I do X" is "Because you don't need
to do X. It's much simpler to do without X" \-- which usually isn't true. It's
much simpler to _learn_ something without X, but X is there to make your life
much easier as long as you can deal with the complexity of learning it. It's
the old "ease of use" vs "ease of learning" issue.

~~~
always_good
On the other hand, people need to learn to take no for an answer and move on.

Instead, egos get involved and a new essay of the week appears on how Elm is
doomed because it doesn't have <pet feature>. That nobody can take Elm
seriously if it doesn't have type-classes, synchronous FFI, derivable JSON
codecs, component state, or whatever the pyre was built on that day.

If you didn't know better, you'd think they were disgruntled paying customers.

Elm's simplicity, lack of abstraction, and resulting boilerplate have more to
offer than helping beginners learn. Nothing demonstrates this better than
coming back to an old Elm application and immediately making meaningful
changes to the code despite a long hiatus from using Elm at all.

There are a lot of languages that continually add features in this space like
PureScript, ReasonML, and even TypeScript.

Why not see where Elm ends up with its aggressive devotion to a minimal API
instead of trying to turn it into a language we already have?

Some of the best aspects of Elm come from its restrictive nature. Like how
every Elm application uses the same "TEA" abstraction which is a breath of
fresh air for anyone who never felt particularly empowered by the paralyzing
abundance of options in the JS ecosystem nor the task of webpack-plumbing them
together.

~~~
vmchale
Nobody can take Elm seriously because _having lines of code in Elm_ is a
liability at this point.

If Evan hadn't wanted this to happen, he shouldn't have positioned it as the
"beginner-friendly" language and then pulled the petty dictator routine out as
soon as people were locked into his ecosystem.

> Nothing demonstrates this better than coming back to an old Elm application
> and immediately making meaningful changes to the code despite a long hiatus
> from using Elm at all.

Or... not having it compile because the BDFL (or, realistically, DFL) has
decided to remove half the features it needed to compile.

------
didibus
I've heard of a few people discontent with Elm for the reasons mentioned in
the article make a very successful jump to ClojureScript and being much
happier about it.

It offers an MVU framework: re-frame. There are others too. Its community is
very friendly and helpful, it loves to discuss the language itself. No one
seems to think of themselves as more knowing. It has never ever broken
backward compatibility. It's a core tenet of the language to never break
anyone ever. Finally, it has very good interop with JavaScript. And its
getting better and better every release.

It's also ran by a BDFL, actually more like two. Rich Hickey as the BDFL of
the standard language design, and David Nolen as current implementer and main
maintainer of ClojureScript. But they're loved and admired. And if you
disagree with their direction, you're free to add your own features as a
macro, that's why they made the language a Lisp.

The language design prioritizes pragmatism. All discussion starts with: What
exact problem are you facing for which there are no simple way to solve. And
working backwards from real problems, solutions are added and new constructs
are built.

The only thing is, it comes from a different school of thought opposite to
strong static types. But it shares a lot in common, emphasis on pure
functional code, immutability of variable and values. No OOP, everything is a
function with support for higher order functions, closures and partial
application. And the same focus on interactive live development.

If you don't mind losing the strong static types, I highly recommend giving it
a try. You'll only miss the nice Elm error messages.

~~~
KingMob
Good suggestion!

Just to clarify one point, though, Clojure/Script does support OOP, with
protocols/records/types, it's just not the first thing we suggest people reach
for in the language. As a community, we're much more likely to use boring
maps/vectors/functions first, and switch to OOP when we really need type-based
polymorphism, or extreme performance.

One consequence of not forcing everything to be OOP (like, e.g., Java) is an
honest evaluation of where it makes sense, and where it adds nothing but
complexity.

~~~
didibus
Well, I don't want to get into a semantics debate, but I can't help myself :p.
And I'm pretty sure Rich Hickey himself would disagree with you about
Clojure/Script having OOP.

Protocols, records and types are not instances of OOP in my book. Polymorphism
and abstract data types are concepts orthogonal to OOP and FP. The fact
Clojure/Script has support for polymorphism and ADT does not mean it supports
OOP.

If you want to claim it supports OOP, I'd say it does in the form of interop.
Genclass, proxy, or defining classes in Java or objects in JavaScript and
using them from Clojure/Script.

But, what is OOP exactly? We can debate this. I like to use Wikipedia's
definition that it is languages where there is a construct, called an object,
which groups together data fields and methods which can access and modify the
data fields within.

Clojure/Script has no such construct. But one can define them in Java or
JavaScript, and use them from Clojure/Script through interop.

~~~
likeclockwork
Records and protocols meet your definition of OOP exactly.

~~~
didibus
Well, like I said, we're in the realm of a semantic debate, and I'm definitly
being pedantic.

But, as I see it, records and types define only data. The former as an
immutable map with pre-defined keys, the latter as a fixed set of data fields.
Thus neither are an object.

Protocols define only function signatures, without data. More like interfaces.
Thus it too is not an object.

Why am I being pedantic? Because data and functions are never coupled in this
case. But in traditional OOP, an object groups data and methods, and are thus
coupled together tightly.

~~~
likeclockwork
But a record defines implementations of the protocol methods. Would you say
Traits in rust aren't an OO construct?

The data and methods are coupled in the record definition. The methods depend
on having the records fields in scope.

~~~
didibus
> Would you say Traits in rust aren't an OO construct?

I'd say traits in Rust, typeclasses in Haskell and Scala imlicit views are the
equivalent to Clojure/Script protocols. And similarly, those constructs by
themself aren't OOP. I think a simple proof is that if they were, then all OOP
languages would have them. But because there are OOP languages (the most
popular ones at that) which don't have them, then it follows this construct is
not fundamental to OOP.

> But a record defines implementations of the protocol methods.

It's better to think of it as a protocol is extended to a type. It is not the
record which defines the implementation. The methods don't belong to the
record, they are independently defined, they can come from a dependency, they
can even be shared with other types and other protocols. This is contrary to
objects which define their own methods.

> The data and methods are coupled in the record definition.

Functions are associated with a protocol and a type independently of the
record or protocol definition. This association is many to many. The same
function can be associated over many protocols and many types. There is no
coupling. You can even dissociate them. To add new associations or dissociate
existing ones, you don't need to touch the record definition at all.

> The methods depend on having the records fields in scope.

They don't. Record fields aren't scoped to their associated methods. They are
always public. There is no self or this scope. They are just normal functions
like any other. You don't even need a protocol. Just write a function which
takes a record and does something with it. Now if you want to make this
function type polymorphic, you can use a protocol.

I'm not sure I'm explaining myself very well. Think of an object. The object
defines some data fields. And it defines some methods together. You can't use
those methods with other objects. The ownership is tied to the object that
defined them. The only way to share the methods is through inheritance.
Similarly, you can only manipulate the data fields of an object through the
object, because the object owns the access to them. Only if it chooses to make
them public or expose a getter/setter are other objects allowed access. This
is OOP. If you model your programs with objects like that, you are doing
object oriented programming. Data is encapsulated behind objects, and can only
be manipulated through sending a message (a method call) to the object. The
object defines the set of possible methods for that data. You can't do that in
Clojure/Script, because no object like construct exists that would allow you
to do it.

Now in Clojure/Script, you have datatypes. That is, data with an associated
type. You can create custom ones, such as records. A record is a set of
key/value pairs with an associated type. A Person record defines a type
Person, with keys Age and Weight and their values. That's all a record does.
It can't restrict access to its data, it can't expose methods, and it can't
receive messages (method calls). You can now write functions that take input
of this new type. Those functions can be defined anywhere. They have no
special access to the data inside Person, there's no `this` or `self`. The
functions don't live inside the datatype. Now, if you want a common set of
functions to work over many different types, you can specify a protocol.
That's all a protocol does. This is just functional programming.

Sorry for the length. The distinctions are subtle, couldn't find a way to
explain them with less words.

~~~
barrkel
The essence of OOP is abstraction via message sends to and from an otherwise
opaque interface. (Really really close to actors, but message sends are
synchronous by default and objects don't have their own thread of control.)
That's what gives you polymorphism; inheritance and encapsulation are down to
discipline. Often implemented as a table of function pointers for performance
reasons, the message sends becoming ordinals into the pointer table, and
losing a certain degree of encapsulation and first-classness in their own
right, like delegation or queuing or other interesting things.

OOP isn't specifically attached to tying behaviour and data together. But if
you only get to interact with state via message sends, and you try and follow
that all the way through so your only non-primitive values are objects (and
perhaps even your primitive values are objects too), then at least some of
those opaque references are going to be mutable. And then you get state into
the mix, and trouble starts brewing.

IMO Rust traits, Go interfaces, Java interfaces are the essence of OO.

~~~
didibus
I mean, yes and no. That's why this is a semantic debate. There are no right
or wrong. Paradigms of programming are not formal concepts.

Some people say the essence of OOP is polymorphism. Others say it is
inheritance. Others say it is the tying together of data and behavior.

I personally find issue with saying OOP is just ADTs + polymorphism. Which is
what rust traits, go interfaces and java interfaces are.

    
    
        Type A
        Type B
        function F(value) {
            switch(typeof value) {
                case A: "I am A."
                case B: "I am B."
            }
        }
    

There, I have achieved object oriented programming. I have values with an
identity, A or B, and I have polymorphic functions over them.

I don't know, it feels too broad to be useful.

That's why I prefer to say that OOP is more related to the tying together of
data and behavior behind an object. This is how the Gang of Four book defines
OO.

I find it frames things in a way that is more differentiating.

So now I can have OO, inheritance and polymorphism in any combination I want.
This means Clojure/Script can now be defined as supporting inheritance and
polymorphism, which it does, yet not supporting OO. And I can have another
language supporting OO and polymorphism, but not inheritance, such as Rust. Or
without OO and inheritance, but with polymorphism like Go, etc.

~~~
pjmlp
> This is how the Gang of Four book defines OO.

That book defines OO from the point of view of Smalltalk and C++.

------
the_mitsuhiko
I think Elm can learn a lot from Rust before 1.0 here. Rust made some "insane"
decisions that should have pissed off the community but did not mostly because
of the way the communication was handled. There were obviously some
disagreements along the way which caused some valuable community members to
jump ship, but overall it was really well handled and the language became
better as a result.

~~~
labster
Elm could learn even more from Perl 6. One of our mottos is "torture the
implemeters on behalf of the users." Another is "hug trolls" and try to turn
them into productive members of the community. Or the even more basic approach
of not removing features without deprecating them for a release cycle. And for
crying out loud listen to your users, as they see edges of the software that a
language designer can miss.

~~~
lmm
And how well has any of that worked out for Perl 6?

~~~
lizmat
Working out better and better, thank you.

------
detaro
The reddit discussion for this post is a telling confirmation of the articles
complaints about the community forums/interaction:
[https://www.reddit.com/r/elm/comments/9a0hc6/elm_019_broke_u...](https://www.reddit.com/r/elm/comments/9a0hc6/elm_019_broke_us/)

~~~
geofft
It is interesting that the message locking the post seems to portray engaging
with people with opposing views about design decisions as _taking time away
from working on Elm_ , instead of being itself a form of working on Elm!

Maybe Elm needs some sort of "Please do not use this language in production"
sign, and no "Community" link at the top of the home page. There's nothing
wrong with a group of folks making a language for themselves / their
employers, perhaps putting it on GitHub because why not, but not having a home
page at all and making it clear that this isn't a stable language for others
to use and they will put much more emphasis on the feedback from their own
experiences than from others'. There's definitely nothing wrong with them
doing that until they get to a 1.0 they're happy with, and then releasing it
to the community.

~~~
G4BB3R
Elm is much more stable than every option in the market. Lots of companies
with 100k+ loc web apps, and 2 companies with 250k+, with no runtime
exceptions in production, due to it's type system. Removing native modules was
needed to keep the language guarantee to not crash in runtime for every
program that compiles.

~~~
geofft
"Stable" as in "doesn't crash in production" and "stable" as in "doesn't
change backwards-incompatibly" are two almost entirely unrelated uses of the
word. Most folks looking for a language prioritize the latter. There's no
point in not having runtime ezceptions if your code stops compiling.

I understand that removal of native modules was required for maintaining (some
interpretation of) the promise of being crash-proof, and that it needs to be
done before 1.0. My point is exactly that the language _isn 't_ at 1.0 yet.

But more than that, my point is about the approach the developers take to the
language, not about any specific decision. I'd still have the same comment
about an Elm which lacked native modules from day 1, or an Elm where they
figured out how to keep native modulea. Not running into breaking changes by
luck is different from intentionally prioritizing stability and other people's
use cases. It doesn't matter how many people are deploying Elm in production
today—it's still a pre-1.0 language and maybe they shouldn't be deploying Elm
in production.

~~~
G4BB3R
I agree with you, but breaking code is not really a problem since elm compiler
is fast and has nice error messages. Porting big code bases takes time, but
it's very worthy imo.

~~~
vmchale
> breaking code is not really a problem since elm compiler is fast and has
> nice error messages.

Not true on either front. Elm's compiler does not have good error messages,
and breaking code is absolutely a problem.

------
erokar
I'm torn about this. I'm rooting for Elm and I think it currently might be the
best frontend solution. I really like Evan's focus on developer UX and
simplicity. This means removing things, making the language smaller and
simpler. And to do that you need to maintain a certain amount of control.

However this seems to have backfired. Too many in the community want this or
that and/or don't feel their opinion is heard. Then they switch to something
else. Unfortunatley I think something like ReasonML will win in the end. JS
interoperability and just enough Algol syntax to staisfy the masses.

Evan is between a rock and a hard place here and it's due to the current
sentiment in frontend dev.

~~~
staltz
I author the Cycle.js framework and for a good while I considered it to be a
sister project to Elm, because both had a focus on simple functional reactive
programming for frontend. I've advocated Elm and been a bit in the community
as well.

Evan is great person, I still remember fondly the time we had good long
conversations at a conference. I started the first attempt at integrating Elm
with React Native, and that was only possible through hacking the native
modules in various ways. I figured I couldn't progress with this plan due to
how restricted Elm is regarding native modules, but also other things like
naming of community modules. Elm is strict not just as a language but also as
a community culture.

What shocks me about the latest state of Elm and its community is how easily
conversations get locked. Locking should be the last resort. What leaders
block or ban indicates what they do not want to risk. There should always be
the possibility of blocking to say that "we cannot afford having X in our
community." and defend some basic principles.

In many communities, X is just personal attacks or harassment, that kind of
thing. The consistent pattern I see in the Elm community management is that X
is dissent. "We cannot risk having divergent discussions (polite or impolite)
in our community" is message that restricts thought freedom and reinforces
cult-like behavior. It's not a good thing to have in a community, specially in
an open one on the internet where membership is fluid (unlike dissent in a
company for example). Curbing dissent ultimately leads to lack of innovation
(which comes from freedom to create without fear of rejection), which
reinforces the status of the leader as the primary source of innovation,
because whatever the leader does is assumed to be never rejected. I think
these community dynamics are bad in the long run, it creates more feeling of
rejection, decreases innovation, and centralizes even more responsibility and
power to the BDFL.

~~~
maxhallinan
Andre's talk "The Past, Present, and Future of Cycle.js" [1] describes how
Cycle was grown by the community through discussion and experimentation.

[1] [https://vimeo.com/216787869](https://vimeo.com/216787869)

------
brokencode
I agree that community management and handling of issues could be better in
Elm, but I’m willing to overlook that due to the terrific quality and
innovation of the end result. Elm has benefited greatly from vision and the
willingness to take risks, which is much easier to do with less communication
overhead and fewer contributors.

Maybe someday Elm will adopt a more community-oriented approach, but I don’t
think that is necessary right now.

~~~
dsiegel2275
If I could upvote this more than once, I would. Spot on.

------
tbenst
I looked at Elm a couple years back and decided on Purescript instead:
[http://www.purescript.org/](http://www.purescript.org/)

Has a much better FFI story with JavaScript than Elm, and has a more powerful
type system (higher kinder types, etc). Row polymorphism makes writing pure
code a joy, the effects system is unobtrusive. I actually enjoy programming
purescript more than Haskell.

~~~
arianvanp
[https://github.com/slamdata/purescript-
halogen](https://github.com/slamdata/purescript-halogen) is a very nice
frontend library with local state per component, such that not the entire vdom
needs to be diffed.

However, if you want an easy migration path, there is
[https://github.com/pselm/core](https://github.com/pselm/core) Which is a
drop-in replacement of the Elm 0.18 API in purescript. You can almost directly
copy your elm code to it and it will work with minor changes

~~~
platz
I like halogen, but elm folks may want something more familiar (and with less
type variables).

~~~
arianvanp
Definitely. One of the 'elm-like' libraries (like the one I also linked) are a
great stepping stone to get started.

~~~
platz
I don't think you even need to call them stepping stones. They are perfectly
fine libraries in their own regard.

Slamdata had some specific requirements with halogen that everyone may not
need. And although the free monad approach is nice, it certainly is not
fundamental or necessarily the best depending on the task to UI construction.

------
iamleppert
I recently took on a contract to fix a busted elm project. There were no
runtime exceptions but it was such a Frankenstein monster I couldn’t believe
it.

If you’re doing any real work on the web, you’re going to have to use external
libraries and code and such. You’re not going to have time to recreate an
entire mapping framework in Elm or whatever and the minute you need to
commingle in such a way you loose a major benefit of such system.

Also “no runtime exceptions” does not mean the application isn’t broken, does
not absolve your developers from real testing and QA their changes.

Also it says a lot when someone wants to call their framework a kernel and
patterns their behavior off you know who.

~~~
bgorman
In general, type checkers almost never catch any errors that wouldn't have
been found extremely quickly in a strongly typed dynamic language.

~~~
skybrian
Having worked in a large codebase to fix type errors in an evolving language,
this is not true. There are plenty of errors.

What is true is that the errors you catch are most often benign and not
obvious, user-visible bugs, for one reason or another. (If they were obvious,
they would have been fixed sooner.) The code might be abandoned or rarely
executed, or it's never called with that argument. Something like that.

Occasionally you do find a serious error, though.

------
dsiegel2275
I would have liked to have seen custom operators stay around in 19, but I
understand the motivations. I think it was in 18 they removed back-ticks for
the same reason. Just makes it way easier for newcomers to learn the language.

As far as I understand it, the native modules lockdown had to take place.
Period. The one thing that most attracts myself (and many others, I'm sure) to
Elm is the guarantees that the compiler gives you towards ensuring no run-time
errors. Give folks the ability to author and publish Elm native modules and
the entire platform loses that guarantee.

~~~
endgame
I don't. If you ban custom operators, how can you find out future use cases
where custom operators make a lot of sense? I am extremely distrustful of a
language where certain people are more equal than others. Those elevated
people could be blessed library authors, or within the core implementation or
whatever, but I hate not being trusted to use my tools properly.

~~~
vmchale
Agreed. Not allowing footguns is great, but custom operators aren't a footgun
and in any case the fact that Elm has operators at all kind of indicates that
they you're just being treated as a second-class citizen.

------
jlengrand
I love Elm. Discovered it last year and loved the language so much that I went
on a conference later in the year on my own budget.

I love how low the cognitive load of adding features is. Having a small baby,
it helps a lot.

That being said, some things really confuse me, and especially the way the
governance model is accepted and cherished. We have a `almighty god` deciding
what will and not be done, the accepted reason being that it's not 1.0 yet.

I mean, with 0.19 coming out, all IDE support went out the window and the
answer from the author of the language is basically : 'changes are known since
last May, things should have been done already. I don't even know what the
status is'. Communication is at the minimum lacking tact. Others could say
straight offensive for not-core users.

I understand PR is hard and not fun. But then find someone to do it for you,
or act as to minimize it.

At the moment, the advantages of elm far outweight the issues for my personal
use. But I really wonder about the long run, but I'm really afraid someone
gets really pissed and forks the language in the long run, fragmenting and
ending up destroying this great community. That would really be a waste.

~~~
yakshaving_jgt
Are you paying to use Elm? What's stopping you from sticking to 0.18? What's
stopping you from building your own 0.19 IDE support?

~~~
jlengrand
This is 100% what i mean. This exact way of thinking is what imho might well
prevent Elm to strive as much as it could.

And btw, I am (modestly) involved in the IDE support. So do check before being
cynical <3.

~~~
yakshaving_jgt
My exact way of thinking is that you are not entitled to anything, and neither
am I.

I run businesses on Elm. I use it because it's the alternative that makes the
most business sense (most confidence that I can release things without them
breaking, and least chance of failure at runtime). I make money with this
tool, and I don't pay to use this tool.

If a better tool came along, I'd use the better tool. So far, Elm is the best
alternative in my opinion. Everyone has this freedom to pick and choose their
tools.

And what does it mean to strive? Scala was a striving language. And? It's
garbage. It tried to be all things to all people, and ended up being an awful
tool.

I find it absolutely amazing that so many petulant children in this thread
believe they are facing some kind of authoritarian oppression because the
language designer said "You know what? Synchronous FFI has almost only been a
bad thing. All FFI should be synchronous from now on."

~~~
jlengrand
First, I'm not sure what makes you think you can just insult me. I'd recommend
you tone it down.

Second, most of what I see here is very similar to my experience:

* I love Elm * I take its pros and cons * The day i don't find what I want there I ll just move out of it. * I do my best to participate in the community as well * Bonus: I also got into Scala and stepped out

The only thing I was trying to convey is : * The creator of the language is
very opiniated (that is fine) * The way of communicating is not ideal (that is
shame, it doesn't have to BE this way). * I hope someone will not really get
annoyed by it to a point where the community will get separated / torn.
Because it would most likely lead to a lot of negativity.

Not sure what brings you to call me a pedulant child. I don't remember saying
I was oppressed. . .

~~~
yakshaving_jgt
I'm sorry that my general frustration with most of the comments in this thread
materialised as being directed toward you specifically. That wasn't my
intention.

People (not necessarily you or I) _are_ going to be annoyed though. And this
is fine. A tool doesn't need to be the most popular alternative to "thrive" or
to "win" (quoting some other commenter now).

The thought process for most people in this thread seems to be:

1\. Get mad when their "freedoms" (dangerous synchronous FFI) are taken away.

2\. Complain, because the programmer knows best (ego/hubris).

3\. Complain further about "the community" when their egos aren't pandered to.

If the maintainers relinquished their ideals, we'd have a language as
dangerous as most of the alternatives. Frankly, I'm not interested in a
"community" where everyone gets along but the software is always broken. I
need my stuff to work.

To you, specifically, I appreciate that you tried to keep the discussion
amicable. Thank you for that, and again I'm sorry.

~~~
jlengrand
No big worries. Insults fly a lot on HN, this won't be the last time. Agreed.
It's not about pleasing people.

Being opiniated is what brought Elm where it is. And it is not about winning.
Definitely agree there too.

I just wish design considerations were communicated in a more positive, rather
than autoritative manner. Because it makes people lose motivation and brings
negativity.

------
the_duke
I only briefly dabbled in Elm and I'm not terribly qualified to comment on
specifics, but I had a similar, negative impression of the way the project is
managed. Especially in comparison to many other open source projects.

------
msangi
I would be totally on board with these changes if an alternative way of doing
things had been offered.

From the philosophical point of view they are exactly what is needed to allow
Elm give as much guarantees as possible.

The sad reality is that very little pragmatism went into this release and now
stuff like web-sockets won't work [1]. This is very surprising because web-
sockets are an use case where the Elm-architecture really shines.

Things like this reinforces my idea that while Elm is a very nice language I
wouldn't want to have it in production, or even in a side project, at least
till it reaches 1.0 and becomes more stable.

[1] [https://github.com/elm-lang/websocket/issues/27](https://github.com/elm-
lang/websocket/issues/27)

~~~
yakshaving_jgt
Why can't this be done with ports?

~~~
msangi
I'm not sure. I haven't looked into the issue much.

In any case, I would expect web-sockets to work out out the box in a language
that is specifically designed to run in the browser.

If that's not working I'm sure that less common parts of the web platform
aren't supported either. Normally I wouldn't care and implement stuff myself
and contribute back, but it doesn't seem to be a realistic option in Elm.

I appreciate that what's there is generally of very high quality, but I cannot
pretend that there aren't many missing pieces and, more importantly, no clear
roadmap

------
noncoml
I was experimenting with Elm around .14 or .15 if I remember correctly. At the
moment the language allowed you to use prime(‘) to name variables, and that
was the suggested way if I had to guess by the tutorials and examples.

During next release they decided that primes as part of a name were not their
cup of tea and removed it. Just like that. When I asked why was prime no
longer allowed, since I couldn’t see any good reason behind it, I got the
usual: “it’s pre-1 release you should expect things to change, etc.”

What left a bitter taste in my mouth was that this change had nothing to do
with the language itself. It seemed as if they decided that using prime is not
good style, so they forbid it.

I haven’t touched Elm since.

~~~
kjeetgill
I think rust went through a huge amount of simmilar changes pre-1.0. I think
everyone was better for it. I appreciate they're taking their time to get it
right pre-1.0. 1.0 is a fairly solemn promise and I respect them for not
taking it lightly.

~~~
noncoml
That’s exactly the kind of answers I got instead of giving me one good
engineering reason on why primes were made forbidden just like this. Thanks
for the demonstration.

~~~
star-techate
The actual reason is probably "when people use primes, they post code that
gets syntax-highlighted by tools that don't know about primes, and this
results in Elm code looking broken and stupid."

~~~
noncoml
Which is not a good reason to ban them completely from one release to the
next. It only shows that they don’t really care about their users that much.

------
kaffee
For those of us who desperately want to put javascript (the entire language)
behind us, many of the "problems" this article mentions are features.

Refusing, on principle, to be inter-operable with unchecked javascript code is
a _defining virtue_ of Elm.

edit: grammar

~~~
vmchale
> For those of us who desperately want to put javascript (the entire language)
> behind us, many of the "problems" this article mentions are features.

Yes, not having FFI is a feature. Brilliant.

------
Libbum
Whilst I get the point about the community leadership being more autocratic
than others, the Elm language itself has always been opinionated - thus it's
difficult to empathise with the rest of the sentiment of this post. An 0.x
release, two years in the making, drops two features such that it can further
fulfil its design goals and everything is ruined?

------
tigershark
I really enjoy the fable-elmish philosophy, I think that the community is
great compared to what the author of this post experienced, but..BUT, the
platform on the whole is just too immature. I remember trying to compile
jquery using the otherwise great ts2fable.. and it was, and probably still is,
pretty much impossible. Or trying to use fable-elmish and getting “undefined
behaviour” in a “hello world” test page. Luckily I discovered pretty soon
these limitations, but I think that when a platform is not battle tested by
millions of people you’ll always get this kind of grief. So just test if elm
or fable-elmish or whatever framework work well for you before committing head
first into it..

------
robert-wallis
One of Elm’s main focuses is code that is not possible to crash. Once I groked
that, native modules going away in favor of ports made much more sense.

~~~
_asummers
Maybe it's my recent living in the Erlang/Elixir community, but writing code
that is not possible to crash doesn't make sense to me. Servers die, machines
get unplugged, network partitions happen, etc. I don't discount that the type
system allows you to specify segments of your program that can be provably
impossible to crash, but doing that for entire nontrivial programs seems like
an impossible ask to me.

~~~
vosper
> Servers die, machines get unplugged, network partitions happen, etc

These things happen in backend / distributed systems. They don't really happen
in the browser, which is basically a self-contained sandbox that can make
network requests. The browser code needs to handle those network requests
maybe failing, but that's about it in terms of dealing with unpredictability.
So, it's totally reasonable to think that a web-app should never be able to
crash.

~~~
_asummers
So if I make two API requests and get some nonsensical data that comes back,
(say v1 from the first request, and v2 comes back from the second because of
some bug in the backend). The program can certainly prepare itself for
validating that data, and reject the v2 if it's not prepared for it, but then
what do you do? To me "crashing" that entire page is a reasonable way to get
around that for some programs. You as a browser can also lose Internet, in
which case you also need to be prepared for things that happen on the other
end depending on the circumstances of disconnection (did my request go out
before it died? should I retry?). The problem is certainly more constrained,
to your point, by being in a browser, but it's trivial to get your program in
a nonsensical state that such that you cannot render as soon as you introduce
external APIs. Perhaps Elm gets around this somehow, but I'm failing to see
how.

Edit: redirection --> disconnection

~~~
protomikron
> The program can certainly prepare itself for validating that data, and
> reject the v2 if it's not prepared for it, but then what do you do? To me
> "crashing" that entire page is a reasonable way to get around that for some
> programs.

Such stuff is mostly handled via types like `Maybe APIResponse` or `Either
ErrorMsg APIResponse`, so the type systems can guarantee that you handle both
cases. And handling the error case (even if it's just a simple message to the
user like "Error: Unable to fetch new weather data for location X/Y") is
better then just crashing.

I mean it depends on your definition of crashing, but I consider it similar to
undefined behaviour. So I greatly prefer

    
    
        $ ./fetch_weather $location
        panic: unable to fetch new weather data for location X/Y
    

to

    
    
        $ ./fetch_weather $location
        Segmentation fault
    

and I guess most people do (where segfault is similar to 500 Internal Server
Error which is equally bad).

------
protomikron
In the end I think it's a good thing to be strict in language design and
openly reject many ideas and suggestions. I guess it's a case of "too many
cooks spoil the broth".

Most languages have too many features anyway so removing them can be a
positive thing.

~~~
vmchale
> Most languages have too many features anyway so removing them can be a
> positive thing.

This is completely unsubstantiated.

------
gonyea
And this is why I love TypeScript: It's just JavaScript, with a type system.
If it's not in the standard then it's not in TypeScript (by default). There's
no risk to adoption.

~~~
Tehnix
Typescript certainly is nicer than plain JavaScript, but it doesn’t come
anywhere near Elm (or PureScript or GHCJS). It really is a world of difference
(edit: in type safety, that is).

The reason for that is simply that TypeScript has to fit in with JavaScript,
while the others do not.

~~~
gonyea
I mean, Dart offers this. The difference between Dart and the other strongly
typed options is that a massive pile of funding (and production apps) drive
Dart and its direction. So it’s quite stable, if a little too risk averse.

That said, I’ve never found Strong Typing to be that essential for front end
dev. TypeScript is incredibly pragmatic, which is why it’s been so successful
imo.

Nothing stops people from writing all their dependencies in TypeScript. But
it’s not necessary to use it successfully.

~~~
Tehnix
What is the “this” that Dart also offers? With the languages I specifically
called out, a LARGE part of them is purity, and not providing the type system
escape hatches that TypeScript/Flow does, to maintain easier gradually
switching a codebase. A nice thing at first, but nothing gained for new
projects.

~~~
gonyea
this = a sound/strong type system:

[https://www.dartlang.org/guides/language/sound-
dart](https://www.dartlang.org/guides/language/sound-dart)

------
willtim
Custom operators make code _more_ readable when used appropriately; and any
aspiring general purpose language that refuses to support them is cutting off
the nose to spite the face.

~~~
zaphar
Any language with a large userbase has a large group of people who don't use
them appropriately. The result is a majority of code that is unreadable. Any
language that depends on people to just "don't do that" is a language that
will be full of people who do exactly that.

~~~
willtim
This is a social problem, it can be solved without such a blunt instrument.
Single letter variable names also make code more readable, but only when used
appropriately. Your argument would suggest banning those!

IMHO it is better to concentrate on getting the semantics right and not waste
any goodwill on restricting syntax.

~~~
zaphar
Yes it is a social problem. But I disagree that you can solve the social
problem without very opinionated and restrictive syntax and semantics.

~~~
willtim
I respect your position, which was shared by the designers of Java and Go, but
any language I choose to use is one that seeks to empower me. For example, the
purity restriction in Haskell exists to ultimately empower me, not because the
language designers have contempt for my abilities.

~~~
zaphar
I also respect yours. This is why there are multiple options in the PL arena
for people to choose.

------
fouc
I just wanted to let you know that a possible alternative functional MVU is
Mithril/Meiosis

[http://mithril.js.org](http://mithril.js.org) \- vdom lib - for the V
[http://meiosis.js.org](http://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: [https://github.com/pakx/the-mithril-
diaries/wiki/Coming-From...](https://github.com/pakx/the-mithril-
diaries/wiki/Coming-From-Elm)

------
hellofunk
Wow:
[https://news.ycombinator.com/item?id=17843149](https://news.ycombinator.com/item?id=17843149)

------
mst
Can somebody take pity on me and explain why the ports system that's supposed
to be used for JS integration can't replace the native modules?

~~~
Tehnix
As far as I know, ports are strictly asynchronous, compared to native code,
which can be synchronous. This means that if you are using native code for
something that is 100% synchronous, you now have to go through a huge hassle
of every calling site becoming async.

------
pjmlp
Another proof that sticking with platform languages is a better option for
productivity, even if the languages might miss a few shinny features.

~~~
yakshaving_jgt
Yeah, productivity.

Because spending 10 minutes writing asynchronous FFI code is definitely worse
than spending a couple of hours debugging a runtime failure.

~~~
pjmlp
It is always funny when people compare external languages to platform ones,
but keep forgetting to include tooling, libraries and eco-system when
comparing them, reducing it to grammar and semantics.

------
k__
Sounds like reasonable removes to me, custom operators are a pain.

~~~
vmchale
> Sounds like reasonable removes to me, custom operators are a pain.

Not the point. The point is that it breaks backwards compatibility for the
arbitrary prejudices of the Supreme Leader.

------
purplezooey
had to realize for a sec that they weren't talking about the mail client

------
always_good
Article aside, the HN and Reddit comments really reflect our toxic entitlement
culture. How many comments here seem to exist for no other reason but to get
in a negative jab of their own?

I'm reminded of Rich Hickey's great response
([https://www.reddit.com/r/Clojure/comments/73yznc/on_whose_au...](https://www.reddit.com/r/Clojure/comments/73yznc/on_whose_authority/do1olag/))
to a similar situation.

------
h4b4n3r0
And that, in short, is why I prefer _really_ freakin' old languages for doing
real work.

------
dcu
These kind of stories make me value Go's approach a lot more. You just have to
worry about making your product better.

~~~
tree_of_item
Go's approach? Go has the same extreme BDFL approach to ignoring community
feedback in favor of the leader's vision. I don't see what is different about
Go.

~~~
didibus
I think the difference with Go is the Google backing. Go ignores community
feedback, but not the feedback it gets from within Google. So at least it can
justify itself by saying, this works for Google, and that's proof enough its
pretty damn good.

Elm's BDFL cannot make such claim, since he doesn't use it to build products
closely similar in nature to most users of Elm. I think this is both good and
bad. Its good in that Elm is more ideological in nature, since the creator is
not motivated to break his ideologies by real world constraints. Its bad,
because people who have those constraints must find ways to shoehorn the
beautiful ideology, into the dirty real world. That's where a lot of the user
pain comes from.

~~~
Skinney
Evan works at NoRedInk which has 250 000 lines of Elm in production.

~~~
didibus
Interesting, I thought he had moved on to doing a masters or PhD.

Well then, I take back some of my hypothesis.

------
knorker
This was confusing to read if you only knew about the email client Elm. In
general I wish people spent more time naming things better, and reducing
naming clashes.

