Hacker News new | past | comments | ask | show | jobs | submit login
Elm is Wrong (reasonablypolymorphic.com)
338 points by HappyAndHarmles on Nov 9, 2016 | hide | past | web | favorite | 207 comments



Despite the abrasive tone of this article, it is true that Elm misses a convenient level of abstraction (whether that be type classes, module functors or whatever).

I spent the first few weeks of my first Elm project fighting against the language, trying to emulate type classes, build abstractions, do things like I would in other languages and generally having a bad time. Eventually, and with slightly bad grace, I conceded to the current limitations of the language and did things the Elm way, accepting that sometimes things are bit boilerplatey and cumbersome.

Now my second large Elm project is currently in its first round of QA, and the difference to similar projects in Angular or React is striking. There are no (and I mean ZERO) runtime errors that have popped up during testing. When QA find a bug, its instantly clear exactly where in the codebase the problem is, and usually simple to fix. So far most serious issues have ended up ultimately being consequences of a poor choice of design/modelling that, when fixed, has ended up in a higher quality overall codebase.

Yes, things could be better, and I'm sure they eventually will be. We would all like the kind of abstractions you talk about in your article, but in my real-life experience it turns out that you don't need them to write powerful and high quality code.

And hey, when these kinds of abstractions do arrive I'll just refactor my code, and know that the compiler will tell me when its done. Imagine doing that in Javascript.


> Yes, things could be better, and I'm sure they eventually will be.

That's unlikely, it is not the direction Evan wants to take, and so far the language has gone the opposite direction on purpose and by design.

> And hey, when these kinds of abstractions do arrive

Which they probably won't. Realise that the Elm platform is written in Haskell, Evan knows about these features, he could have used them and he very specifically avoided doing so. If you want these abstraction-building tools you'll be much better off looking at e.g. PureScript rather than wait for Elm to add them.


I disagree - I think that firstly Evan wants to implement the right abstraction (which he doesn't think is traditional Haskell type classes), and secondly its simply not a priority.


>> trying to emulate type classes, build abstractions, do things like I would in other languages

I am pretty sure I read somewhere on the project homepage that you should not do this but do things on the elm way.


I'm not particularly interested in Elm, but basically this post is about one problem in the language. One. This doesn't make the language a pile of garbage as the author seems to let you think.

I'm a Python programmer. I fully expect dict keys to be able to be arbitrary objects. But after coding a lot in JS, I realized I could live without it. It's nice, but it's not a show stopper if I don't have it.

Same goes here. Yes, typing is not as good as you wish it was, but Elm is a young language, give it time to evolve. In the meantime, what about the innovative things in it ?


> I'm a Python programmer. I fully expect dict keys to be able to be arbitrary objects.

I'm a Python programmer too, and I also fully expect dict keys to be able to be arbitary objects, and I get really frustrated with the fact that they can't be arbitary objects. They have to be hashable objects, and the hash function refuses to hash certain objects that it has decided aren't allowed.


Well, you cannot use a mutable object as a key without some help. What would you expect to happen if the object is modified after being inserted into the dictionary?

If you have a list or dictionary you want to use a key, you can convert it into a tuple which would make it immutable.

If you don't care about performance for larger collections you could just use a list instead of a dictionary, which does not require hashing. Changes to the original mutable object will also be reflected in your list.


  > What would you expect to happen if the object is modified after being inserted into the dictionary?
I would expect it to continue to use the object. Why would it matter if it was mutated or not?

You can try it right in your browser with Javascript and the Map() object type. You can mutate the object all you want, as long as it's the same object(-reference) you access the same value in the Map object. Just as I would expect. "Mutable" doesn't change which object you have, only what it looks like inside.


This is where Pythonistas rely on the idea that "we're all consenting adults here". It's very useful to let objects assert that they have an arbitrary, immutable hash value. I've used that ability in Python and it solved problems that would have been very challenging otherwise. Of course, that ability also leads to undocumented behavior if hash values change. Python coders expect dicts to behave in undocumented ways when object hashes change, but it would be a bug if that led to a segfault or a C assertion failure.


I'm genuinely curious how/why this is a problem for Python yet I've never heard of it being a problem for C#. In C# you can override Object.GetHashCode(), and there's no way in C# to even express the constraint/desire "the result of GetHashCode doesn't change (especially after insertion into a container)". Yet I've never heard of anyone in C# having a problem using mutable objects in sets or dictionaries?


To be honest, most Python coders probably never get deep enough in the language to start overriding hash values, and those who do probably understand the implications before they get that deep.


This fundamentally reduces the usefulness of hash representations though. Instead of thinking of dict keys, think sets.

It's also worth pointing out that user-defined objects operate the way you seem to desire (e.g. default to using the id() property of the object to derive the hash). So in my mind, this strikes the perfect balance?

StdLib types that are immutable bake in more comparative hash properties while making it trivial for a user to wrap them and override this richer behavior with default hash based on id().

Consider:

```

>>> class myList(object):

... def __init__(self):

... self.inner_list = list()

...

>>> x = myList()

>>> x

<myList object at 0x10bdabf10>

>>> x.inner_list

[]

>>> y = {x: 'hi'}

>>> y

{<myList object at 0x10bdabf10>: 'hi'}

>>> x.inner_list.append(1)

>>> x.inner_list

[1]

>>> y

{<myList object at 0x10bdabf10>: 'hi'}

>>> for k in y.keys():

... print k.inner_list

...

[1]

```


  > This fundamentally reduces the usefulness of hash representations though.
If you want something immutable just put something immutable in?

  > Instead of thinking of dict keys, think sets.
It's the same that I already wrote for sets, and also the same I just wrote: If you want something immutable just put something immutable in.

By the way, I'm not talking about any particular implementation.


I think there is a disconnect here, I showed you how you could place a mutable object as a dict key in Python. One which uses the object itself (id() property) for the hash.

> If you want something immutable just put something immutable in.

My point is what do you expect if you do this:

>>> x = (1, 2)

>>> y = (1, 2)

>>> set([x, y])

I would argue that you would expect:

>>> set([(1,2)])

Since x is equal to y. But if you base the hash by default on id, you would get:

>>> set([(1, 2), (1, 2)]) # set([x, y])

Since x and y are different instances (have different id()) properties. I would argue that it's more useful/predictable for built-ins to hash based on content rather than id().

However, you can still hash based on id() but simply creating your own object (as I demonstrated). So you get sensible defaults for built-ins but also the option of hashing mutable objects.


We were originally talking about a dictionary key, and the purpose of an object as key in a dictionary is AFAICS to associate a value with that concrete object. Whenever I use those structures I have to solve an engineering problem, not a math problem. I would claim that's the majority of use cases, a claim that seems to be supported by how it is commonly implemented (see Java below and Javascript for two of the most common languages).

Anyway, it's configurable for example in Java (http://stackoverflow.com/questions/9440380/using-an-instance...) - default is to use the reference but you can override object methods to change that. Similarly for C#(http://stackoverflow.com/questions/634826/using-an-object-as... or http://stackoverflow.com/questions/8952003/how-does-hashset-...).


Ah I see the disconnect, I think the underlying piece I glossed over was the fact that dict objects and set objects rely on the same hashable property of objects. This is in part due to the "one way and only one way" rule of thumb of Python's language design.

For me, talking about how dicts handle hashing keys and sets hashing members are equivalent in the context of the Python language.

Given that context I was saying changing the "hashable" nature of default objects would be counter-intuitive as the new behavior would be in contrast to the expected behavior of sets and/or immutable equal types in dict keys.


> What would you expect to happen if the object is modified after being inserted into the dictionary?

This question is sometimes not important: When the mutable object is not mutated.


> This question is sometimes not important: When the mutable object is not mutated.

Which you can't guarantee when the object is mutable, so for consistency's sake it's left out.

Though you can always build your own Dict subclass and implement __hash__ on it and be angry with yourself when it fails. :)


I was going to reply to him, but you beat me to it. But since you posed a different question regarding the term hashable, I thought I would link some helpful starting docs (for you and/or others):

https://docs.python.org/3/glossary.html#term-hashable

http://stackoverflow.com/questions/4348232/python-dictionary...



Come on, how many time in your entire life did you need this ?

For set, it's a bit more annoying. But for dicts. twice in 10 years maybe ?


After a few years of Clojure(Script), where immutability means you can use almost anything as keys, I have found many cases where my python code would have been simpler and easier if I could use arbitrary objects (and therefore data structures) as keys.

I mean, its not a huge deal, but it adds up.


> I have found many cases where my python code would have been simpler and easier if I could use arbitrary objects as keys

You can use pretty much anything as a dictionary key


That's really not true[1]. You can only use hashable types, which excludes dicts, lists and sets.

For example (tested on both python 2.7 and 3.4):

    >>> {{'a': 1}: 2}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'dict'
    >>> {[1,2,3]: 4}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    >>> {{1,2,3}: 4}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'set'
Objects inheriting from object are hashable by default, but the hash is based on the objects instance such that each instance will return a unique value for that instance:

    >>> class A(object):
    ...     def __init__(self):
    ...         self.x = 1
    ...
    >>> a = A()
    >>> b = A()
    >>> d = {a: 1, b: 2}
    >>> a.x = 10
    >>> b.x = 10
    >>> d[a]
    1
    >>> d[b]
    2
While this makes sense for the instance stored in the dict (because mutability would otherwise mean that they key changes values), I don't think this is particularly useful. I rarely look up dicts by instance, but rather by value. That is, I would construct another object with the same attributes and look up by that.

You can, of course, implement your own __hash__ to make it work, but you have to do it manually for any object you want it and most third-party objects won't have implemented it so you'd have to monkey patch them.

Contrast that with Clojure, where all built-in data structures (maps, sets, lists, dicts etc) work as keys out of the box.

[1] I guess its true in the sense that you can implement __hash__ to make it work. But its not particularly easy or idiomatic.


It has been quite common when wanting to use a dictionary as a cache or counter such as a function cache or to count how many times a function is called with certain arguments. If the values of the arguments aren't hashable it doesn't work.


As an aside, what happens in Python when you try to hash objects that contain circular references?


Not all problems are equal. Most problems can be compensated in some way or another, using abstractions. Problems that limits abstraction are grave, for it puts a glass ceiling that can't be got around.

A language designer may limit the power of abstraction intentionally; maybe the abstraction taxes performance too much; or maybe too much power scares the target users. That's a plausible choice, but that also turns some users away.


JavaScript maps can have object keys, you're just using objects as dictionaries. Objects in python don't typically have non-string keys.

```js var m = new Map(); var o = {}; // some object m.set(o, 5); m.get(o); // 5 ```


Map are not supported by most IE version, and even IE 11 doesn't support half of the API. The android browser doesn't support it at all either. Bottom line, you couldn't not have used Map during the last past years, and used objects for dict.


Not too much people write plain JS anymore, and it is not that hard to build transpiling pipeline. Sometimes you have a small project and you don't want to deal with all this nonsense, but then you are writing code in one file and it is very small jquery style enhancements.

So, if you need objects as keys in dictionaries, then there is a big chance that you can use transpiling already (modules, other ES6 features).

Please, don't take it as an offence, just a suggestion – I really don't see a problem here.


> ```js var m = new Map(); var o = {}; // some object m.set(o, 5); m.get(o); // 5 ```

That guy who thought markdown was supported by hacker news. LOL ! I've been through that too...


>There is no "map" function, but there are "List.map", "Dict.map", "Array.map" among others, and none of them are related to one another. This is not only annoying, but also breaks the abstract data-type guarantee: our call-sites are now tightly coupled to our implementation details. If I decide to change from a "List a" to an "Array a" for efficiency reasons, my whole codebase needs to know about it.

I can accept this in old languages. I can accept this in embedded languages. I cannot accept this in a language that is supposed to be about programmer productivity.

Basically this patient has one bullet hole in their heart. One. This doesn't make the patient dead as the author seems to let you think.


I agree; to me it says equally as much about the expectations of the author of the article. In C++ you can define operator < and in C# you can define IComparable. Therefore I was astonished to discover the datastructures in the dynamic language Io can't be extended to use custom comparators. It's just an implementation limitation: Io's datastructures are all written in C and so there's a fixed set of types they use for keys. It is what it is.

On the other hand C++ is only just about to get its first version of Concepts. (Haskell programmers in this thread: imagine if you waited 10+ years to get typeclasses.)

My point being that most languages are going to be missing something you wish they had.


One problem that makes it sound like a nightmare to work with.


First, let me say that I think Evan has done amazing work with Elm, and Elm is a very interesting language on several fronts. It is a positive contribution to the world, especially the idea that error messages can be great and compilers and type systems are tools.

That said, I agree 100% that the ability to form abstractions is a critical part of any language that hopes to become a tool that larger teams and projects can adopt. Without type classes and convenient mutability, I don't see Elm achieving widespread adoption. (That said, it could gain those features in the future.)

I've been working on a language inspired to some degree by Elm but also by my experience teaching Haskell. Haskell has amazing expressive capabilities and type safety, but the unfamiliar syntax is a hurdle that many people don't care to jump. To that end, we've designed Crux to have much of the expressive power of languages in the ML/Haskell family, while being as familiar and lightweight as JavaScript or Python. The idea is that it's something you can pick up easily but it can grow with you and your project.

Some articles on the design thinking: https://chadaustin.me/tag/crux/

The website: http://cruxlang.org [It's a preview!]


I don't believe in Elm one bit. it's been 4 years guys. I follow its developement (it's not a hard thing to do after all, it's a snail pace) because its creator is intelligent and there are a few nice things in it.

But as a practical platform to build real apps? No way. I mean you can build apps with any tech, so of course people will try and succeed with it; but it's just a bad choice.

Elm is impratical because you can't do anything with it. I loathe directing attitudes in that field where everything moves fast (http://www.martinfowler.com/bliki/EnablingAttitude.html).

Its creator is a bit on the control freak side and far more of a backend dev than a frontend dev. The reactive framework (the Elm architecture) is full of boilerplate and anything that was not forethought will have to be a metric ton of more boilerplate or delegated to javascript via asynchronous ports (if you have to hide the crap away in JS land because it's impossible to do in elm, somehow it's not elm's problem). The elm community is minuscule and not always great, doesn't embrace new approaches (the ones who do don't stay for long as it's so frustrating) they're more like robots repeating "wait for Evan to tell us how to do that. If Evan didn't say anything yet, you are taking big risks" or "Evan is working on this particular problem, just wait 2 years"

Meanwhile we can build apps real fast with typescript, which in version 2.0.3 is a very capable and more than typesafe enough language.

bucklescript/Reason might be a good alternative to the very closed Elm ecosystem too if like me you like ML.

I think where elm shines is as a simplistic language and sanitized environment to teach people programming. That's about it. It's still in a state of a "research language" (and it's good at it), but is not being marketed as such.


Rejecting a programming language feature because you find it constraining is just ignoring history. Arguments similar to yours have been used to dismiss Garbage Collection, type systems, and even the use of high-level languages, all of which were very successful precisely because they constrain the set of programs you can write.

Also, why all the hate? As you said, neither you or the TypeScript community have any reason to feel threatened by Elm, which nevertheless has had a very positive influence on the mainstream JavaScript community (look at Redux).

The only impact your comment could have is discouraging the Elm community from furthering its valuable research in the field of web development. Please write constructively next time.


There is no hate here. Elm's current objective is to go mainstream. I just say it's not good yet. I agree with you, Elm is very valuable as a competitor.


what is the feature you're talking about? I don't see any innovation in elm on the order of a GC or a type system. Perhaps you're referring to Elm's "feature" of removing the ability to create abstractions away from the programmer so that everything must be done by copy-paste and brute force.


> Meanwhile [...] typescript, [...] is [...] more than typesafe enough language.

For someone who hasn't worked with a statically typed language yet, perhaps. But someone who knows and works with Haskell would disagree here.


Depends. I also work with scala. Yet somehow I don't need monads, functors, applicatives, etc on the frontend. TS with the right strictness flag enabled, is a good, practical middle ground for now even though I hope a good compile-to-js/assembly will be useable soon (I still have yet to try bucklescript/reason for real)


Since you work with Scala ... have you tried Scala.js?


This post starts off with an abstract goal - "use a custom type as a dict key", and then goes off down a rabbit hole trying to create typeclasses and make it work. This is despite prior knowledge that Elm has chosen not to implement type classes.

The line from Evan, Elm's creator, has always been along the lines of "show me a concrete actual use-case that you can't do without typeclasses", this article fails to clear that fairly low bar.

The other elm article from the other day about select boxes did a much better job of identifying that not having a way to enumerate Enum types is a bit annoying.


> The line from Evan, Elm's creator, has always been along the lines of "show me a concrete actual use-case that you can't do without typeclasses", this article fails to clear that fairly low bar.

Translation: "I will never add typeclasses."

There is no concrete actual use-case that is impossible to implement without typeclasses. What typeclasses make possible is an abstraction over concrete actual use-cases. That is, you can always solve individual concrete actual problems with boilerplate. Typeclasses "only" give you the possibility to write that boilerplate once and for all and reuse it for every concrete actual use-case.

Evan seems to think that that's not worth it, which is a valid opinion to hold. But it would be a bit more honest to come out and say it like this.


Evan has several times said that he's open for typeclasses. Problem is that they have a profound effect on the language, and so they have to be done right. He doesn't know what the right implementation of that might be at the moment, so he's waiting until he comes up with what the right thing to add for Elm would be.


You think Evan is just waiting around for the right abstraction to dawn on him? It's been years with not one bit of code written in the direction of adding a mechanism for abstraction in the language (whether that be typeclasses or something else)


"Code is the easy part"

First you need to figure out what exactly the Elm community wants and needs. Once you have a pretty good idea of that, you can start prototyping things. Elm is still young, and the most pressing concerns for using Elm in production is not the lack of interfaces/protocols/typeclasses, but stuff like debuggers, which is what Evan is working on.

I'm sure we'll see some tool for ad-hoc polymorphism in the future, but not in the short term.


Blind faith might be enough for you but I don't buy it. The original issue was 3 years ago.


I do have some sympathy for the author's desire to have record extension (re-)added, as that looks like a pure win, from my outside perspective. Maybe there are concerns which insiders may be better able to spot, like losing some reasoning ability.

As for typeclasses, I think Elm's stance is perfectly reasonable. Typeclasses aren't a pure win, they have downsides too:

- They couple the term level to the type level by allowing values to depend on types. This makes it impossible to compile or interpret a program without first checking/inferring its types. Static types without typeclasses don't have this problem; as far as I can tell this even includes dependent types (which do their coupling the other way), as long as you don't allow some form of typecase.

- Global uniqueness of instances doesn't compose. If I have a perfectly correct module A, and a perfectly correct module B, a module C might break by importing both, due to overlapping instances. This has to be mitigated by convention, e.g. not writing orphan instances.

- Local reasoning can require knowledge of global properties. This is especially true for things like code generation. For example, if I plumb together two expressions, say `nub :: Eq a => [a] -> [a]` and `xs :: [b]`, I can generate new requirements like `Eq b`. However, I can't just go ahead and implement those requirements (e.g. generating an `Eq` instance for `b`), since that will break if there's already an implementation, floating somewhere in the sea of imported modules. Packages like `ifcxt` can help, by allowing lookups and fallbacks, but they're not a complete solution.

- If more than one instance of a typeclass might makes sense for some type, it's pretty much inevitable that APIs using the typeclass (e.g. `foo :: Bar a => a -> ...`) will gain extra functions for bypassing the typeclass (e.g. `fooBy :: (a -> ...) -> a -> ...`)

There are probably more issues in the literature, but these are ones I've been banging my head against recently.

Typeclasses are a great idea and a useful addition to the PLT toolbox, but including them in a language isn't an automatic improvement: it's more of a design choice to steer the language down a particular path, when other languages may prefer other paths. Similar to using strict/non-strict evaluation, or exceptions, or macros.


Record extension was removed because it allowed Evan to improve error messages, and because he found that Elm's power users didn't use the feature.


I have some similar thoughts when trying out Elm.

Every function that a language support/does not support shapes the ecosystem, and that is arguably as important as the language itself. With Elm, decision making is done by a small group of people and they can be quite opinionated.

I started when 0.15 is out, amazed by how beautiful FRP can be, then it is gone now. I cannot add / remove fields from dictionary, I cannot have multi-way if. My code base is still simple, so I can get around it, but I really enjoyed the good old FRP style. In JS, you can definitely choose your favourite frameworks, but in Elm, there is no alternative, there is only a single HTML framework `elm-lang/html`, if they decide to drop FRP, you cannot escape! This also means choosing Elm is also choosing to follow Evan, you are betting on a person.

I hope things getting better someday, we will have a standard JS interop that allows people to make their own 3rd party frameworks in Elm. Competition makes things better.


could you explain what you found better between the old FRP style and the new subscriptions style?

I am not an elm user, but I follow from time to time, and they seem substantially equivalent looking at the migration guide[0]

[0] https://github.com/elm-lang/elm-platform/blob/master/upgrade...


PureScript!


I tried Halogen for a while and found it too complicated. I need to create a type with 6 type params (something like `ParentComponentSpec s s' f f' g p`) for embedding a child component! Also, most of the operations are wrapped in monad, which ultimately bring me back to the procedural way of thinking.


Pux is great!


Wow, I never heard of that! Thanks, will check it out :)


As someone who's written a language, the need to have a personal approval from a founder before being published to the site stuck out to me more than the typeclasses. I'd argue in favor of it, so long as the review is done in a timely process. I can understand wanting a smaller number of high-quality, reviewed libraries that are tested and shouldn't break.


The restriction only applies to native modules (modules that ship with Javascript): https://groups.google.com/forum/#!msg/elm-dev/1JW6wknkDIo/H9...


I think understanding the why is also important here. Native modules exist essentially for side effects. A bad native module undermines all the safety Elm provides.


If you want to write anything non-trivial in Elm you need to use native modules though because the language doesn't give you access to any of it's "magic"


This post is way too angry. The problem it describes is legitimate, but still just a problem to be fixed.

Having the language maintainer need to bless packages with native bindings is strange, though. Tag the packages so that people know they use native bindings, then people can decide whether or not to trust them. You cannot build an ecosystem through one person.


Like most angry rants, it ignores the fact that it kind of is a fixed problem. http://package.elm-lang.org/packages/robertjlooby/elm-generi...


I didn't do any larger projects, so far my time with Elm was enjoyable, language and tooling is very good and interesting.

I don't like the tone of this article, otherwise critique seems to warrant more discussion. Elm as a language is in development and community is very vibrant and open... as long as you don't mention rules for formatting, one in particular ;). So, I really wouldn't discount Elm so quickly.

On the other hand, PureScript and Reason also look very interesting and I am looking forward to get more familiar with them. I think we live in fantastic times.


I enjoy Elm, and I think improvements are welcome. In particular, I would like to see some improvements to the Elm REPL such as type inference and documentation strings.

The article makes some great points; however, the title is not particularly useful nor a good summary of the article itself.


Elm is great and Purescript even better. I haven't though heard anyone building apps using Elm on both back-end and front-end.

I have enourmous respect for Anders Hejlsberg and his work but Typescript is not an answer. Typescript is limited in sense that from the beginning it was doomed to be just a superset of Javascript. And we all know about deficiencies and "bad parts" of Javascript.

Languages do matter and those with strong functional emphasis are better, because they enforce you to pursue specific discipline that allows you to write better code.

Of all functional languages (more or less popular today) in my opinion the best option is Clojure and Clojurescript. Clojurescript is simply amazing. It's robust, easy to learn, fast, adaptable, pragmatic, can cover your needs on all major platforms including iOS and Android. For a long time advocates of statically typed languages would point to one "weakness" of Clojure - its dynamically typed nature. But to begin with dynamism of Clojure types always considered its strength. Besides, Clojure today carries an instrument far more powerful than static types - http://clojure.org/about/spec. Clojure community is growing, language is gaining popularity. Because behind seemingly innocuous, and even arguably (at the first sight) not very appealing lispy syntax, there is an incredible elegance, power and true astonishment.


I was vaguely under the impression that Elm was more an ML style language than a Haskell style language, so it ought to have modules and functors rather than typeclassss.


SYTC is in reference to a comment made pre Elm 0.17, when drastic changes were made to the language (FRP was dropped, ports were massively simplified, and a bunch of other stuff).

So he then decides he wants to have the full Elm experience by trying to replicate a Haskell solution in Elm using a technique that was mentioned in an issue comment. I feel like in trying to avoid the blub paradox, he ran right into it.


It really seems like Elm should implement typeclasses. I don't know Elm, but I can't really imagine writing serious Haskell programs without them, and I've seen multiple Elm-related complaints today that were either directly lamenting their absence or lamenting difficulties that they would have solved, trivially.


Keep in mind that Evan works at a company that has 55k lines of Elm in production. Neither Evan, nor the lead-developer of the company, feel that typeclasses, or something like it, needs to be in the language right now.


> Neither Evan, nor the lead-developer of the company, feel that typeclasses, or something like it, needs to be in the language right now.

Need is not the word I'd use. IIRC (from some Github issue I saw recently) Evan has said they are adopting a "wait and see approach" on typeclasses and/or other type system extensions. Given how young Elm is, I see this as a careful and considered approach to its continued development, rather than a statement that its creators consider it to be finished and complete as it is at this time.

I've jumped ship on things for far less than a "need", just because there was something better. I expect that a lot of people use Elm despite any perceived deficiencies because they think it's still better than the alternatives for their application(s).


Read the two last words of that sentence. I agree with you, I use Elm every day.


I'm not sure what point you think I'm trying to make. A language can be better than its competitors/alternatives while still having room to improve.

I'm not saying "Elm is bad", or whatever.


Here's how I view our conversation thus far. I said "Evan doesn't feel the need to add typeclasses right now." You said "He is thinking about maybe adding it in the future." Then I said "I know, that's why I ended my sentence with -- right now --" and then you said "what are you talking about? I'm not saying Elm is bad!"

> A language can be better than its competitors/alternatives while still having room to improve.

I agree with you is all I'm saying. I never tried to imply otherwise. All I said is that there is no reason to think that Elm has to have typeclasses right now to be useful, as some others seem to suggest.


This is unconvincing to me. Just because Evan and his friends are happy to write boilerplate and copy-paste the same stuff over and over doesn't mean it's the right thing to do.


Hi! I work at NoRedInk, the aforementioned company with 55,000 lines of Elm in production.

We don't "copy-paste the same stuff over and over." That would suck. Why would we be excited about a language that made us do that? Our Elm code is about as DRY as our JS code was before, except the Elm code is way easier to maintain.


How do you compose update functions without writing the boilerplate let ... in for every Msg? How do you stop your main update function from growing endlessly as you add new Msgs?

You need only look in the standard library for examples of boilerplate and not-DRY code. The map function is implemented separately for Lists, Arrays, etc.

I really want to love Elm. But the more I wrote it the more I realised that the only answer to those questions is that you solve them with boilerplate and brute force. When I ask the community what the solution is I'm largely ignored or told it's not a "real" problem.


> How do you compose update functions

If there's shared logic between update functions we extract it into a helper function. That also makes it easier to test.

I'm not sure how typeclasses would make composing update functions easier, but in this case we can be concrete. PureScript's Pux library implements the Elm Architecture, and PureScript has typeclasses. Would you mind showing me some Pux code that uses typeclasses to improve the situation you're talking about?


Extracting to a helper function doesn't change the fact that there is boilerplate that must be overcome by brute force when composing "components". Every sub update function needs to be manually wired into the main update function since the introduction of Html.app. Libraries like elm-return make this a bit nicer to work with, but because of the restrictions in what Elm will let you do with it's "magic" there is no alternative.

I don't write PureScript, I can't help you there.


Don't understand how typeclasses would help you here. If you want immutable single source of truth, which is what Elm provides, you would do the same thing in Javascript/React and Clojurescript/Om.

I follow the same pattern in a 10k Javascript/React app I'm working on professionally. I don't see another way of doing things. Not that I'm looking very hard, cause this really isn't a problem.


It should be mentioned here that if map had the same implementation for both Array and List, map for arrays would probably be 10-20x slower than what it is today.

In that case, is it really boilerplate?


Yeah, that would be an example of where even if that langue feature existed, using it would lead to a worse implementation. :(


What is "the right thing to do"? Depends doesn't it? Just because other languages have support for something like typeclasses, doesn't mean that it's the right thing for Elm to have.

The fact that NoRedInk are perfectly happy without typeclasses (or something similar) could be an indication that it really isn't as important that people would make you believe. After all, there are several languages out there with support for typeclasses (or something similar). Like purescript. And yet, people decide to use Elm.


Perhaps not, but it seemed like an issue even in small sized apps that I wrote.

I think that Evan and Richard are personally invested in the language and can't see it's shortcomings.


Such aggressive tone, no need, very off putting and unconstructive. If I was considering employing the author and came across this article I'd be seriously put off despite the fact he clearly knows a thing or two.


> very off putting and unconstructive

One of those is irrelevant and the other one is false.

There's a lengthy, clear description of a problem, with a use case, leading up to a feature request...how is all of that "unconstructive"?

In fact, what's definitively unconstructive is the way the feature request is closed: dismissing the use case as invalid, despite the fact there's a description of the rationale behind it in the comments.


To clarify, the aggressive tone is non-constructive, as in it detracts from the article. You're right he makes a constructive point but I bet a bunch of people don't bother reading that far.


So what if the tone is aggressive? It's a venting piece. It says so in the second paragraph. Who cares if people bother reading it? Where it mattered - the actual github request - the tone of the discussion is right on point.

People who ignore the point to come here and complain about the tone, also further detract from the point.

FWIW, I find it extra hilarious that, in the context of employment search, I would form an opinion based on how - or what - a person _vents_.


How people vent is a very important consideration, when they're likely to vent at you at some point.


It seems most of his issues stem from the language and the FFI, not necessarily the TEA style 'library' (which he claims is 'great' at the start). There is a Haskell -> JS compiler and an OCaml -> JS compiler, as well as Bucklescript, which is another OCaml -> JS compiler but actually outputs very normal looking and readable JS, probably be better to use those.

Consequently I had many of the same complaints, though not quite to the extent or wording he does, so I made my own TEA-like library on Bucklescript/OCaml and ported many of the Elm examples to it, most were basic copy/pastes with the most minor of syntactical differences (`with` instead of `|` and so forth, basically Elm->OCaml differences), I have it up (with code link) at http://overminddl1.com/bucklescript/ if anyone is curious. Not production worthy by any stretch but I do clean it up and add more and more to it over time, already can do near all that Elm's libraries can do, in addition to some of the community libraries.

Continuing on the article, he basically re-implemented OCaml's Witness style (done via OCaml's modules), it was fascinating watching someone build it in Elm I must admit.

He does focus too much on typeclasses, the witnesses he wrote is the way OCaml does it (although with a bit less syntax, and much more an upcoming update), which is not a typeclass form, but something similar.

An aside, where he mentions 'If you don’t want to read the essay, SYTC essentially says “hey, why don’t we pass around an object that describes the implementation of the contract that we care about, rather than having the compiler infer it for us?”. If you’re familiar with Scala, this is how they implement typeclasses in terms of implicit parameters. If you’re not, SYTC is equivalent to passing around a vtable whenever you want to invoke code on a dynamic target.', that is just what OCaml is doing in a soon-coming version with its implicit modules. Definitely looking forward to that, even if they are just fluff. They are basically like Scala's implicit parameters but with type lookup based on module definitions, still explicit, but significantly reduces the code required to be written.


"my friend and I decided to hackathon our way through an app to help us learn how to play guitar."

this sounds like a great way to never learn to play guitar


  >I have complaints about Elm after using it during a quick hack session.


The post is opinionated and a bit aggresively worded.

But his(/her?) major complaint is valid: lack of type classes, which completely kills essential composability and generic properties of Haskell. And the module system doesn't offer MLs features to make up for it (signatures).

This means that Elm requires boilerplate for things that are elegantly handled by type classes.

You may also look at Purescript [1], a more complete Haskell inspired language compiling to Javascript.

Haskell is a complex language. So I'm not necessarily saying that Purescript is a good choice for the average developer unfamiliar with functional languages.

Elms 'lack of features' makes it easy to pick up. Especially if you aren't familiar with FP. But Elm is TOO simple.

[1] http://www.purescript.org/


You can do everything that you can with typeclasses without them. In fact GHC compiles Haskell into GHC core, where are no typeclasses.

See http://okmij.org/ftp/Computation/typeclass.html


Quote from the second paragraph:

> Knowing what TEDIOUS JOB GHC is doing for us helps us appreciate more the convenience of type classes.

Thanks for the link though, I think I read it a few years ago.


In truth, it's a balancing act. More than a few Haskell libraries are more tedious than Elm code (I've written upwards of 8,000 lines of production Elm but have been doing Haskell for much longer) because they're so intensely abstract.

Without typeclasses, that simply doesn't happen. I'd say 90% or more of Haskell typeclass usage is pointless, and maybe half of what remains is simple to replace with simpler polymorphism or no polymorphism.

For instance, almost everything here:

https://wiki.haskell.org/Typeclassopedia

is replaced, in Elm, by just having an explicit module reference, so Maybe.andThen instead of andThen. No joke, that replaces essentially all of it, except some stuff that's not used that often.


You're way more experienced than me in this, but it seems to me that anywhere you're going to be replacing polymorphism is going to result in more typing. If you know the module that you want, then it is trivial, but the point of type classes (IIUC) is to write generic functions that can act on a variety of types.

To replace the non-trivial cases is going to require pattern matching, it seems. If your types change, then you are going to have to update things in multiple places.

But, like you said, it's not the end of the world. In many cases the intent will probably be clearer. Still, I'd rather have type classes than not.


Typeclasses aren't bad, that's for sure. I kinda want something as flexible as typeclasses and derive generic but no where near that complex. A big part of me says I could do well with just promising some JavaScript really really meets a type signature. Ports are great for side effects but I there might be room for this for pure functions?


You can do everything you can do in Haskell also in assembler. Haskell compiles down to assembler, where there is no Haskell.


Yes, you can, and the resulting code is an unreadable, unmaintainable mess after two weeks.


> the language is an unsurmountable pile of poorly-thought-out and impossible-to-compose new ideas on top of the least interesting pieces of Haskell

For a Haskell programmer, what he tried to do (use typeclasses) is extremely common. It's some of the most basic stuff you can do. Elm is clearly modeled after Haskell, and absolutely fails to maintain the basic patterns that Haskell users take for granted.


The thing is Javascript programmers are the target audience for Elm not Haskell programmers. I can understand the frustration if you're coming to Elm with a Haskell mindset.


If you only consider criticism from people deeply invested in a platform, you'll get a really skewed perspective.

Put another way: if you try something and find it flawed—why should you put any more time and effort into it? And yet, that doesn't mean the problems you found were not real. If anything, those problems might be the most relevant because they forced you to put the tool down.


I disagree strongly with the tone and language of this article, but I think it actually contains an interesting and nontrivial analysis and shouldn't be outright dismissed (though its title probably should be).


If anyone using elm runs into the same dictionary-comparable issue, please understand that it's a solved problem: http://package.elm-lang.org/packages/robertjlooby/elm-generi...


The problem is the compiler magic for what is 'comparable' is unavailable. This doesn't solve that problem. It creates an entirely new data structure that is mostly a copy paste of the stdlib Dict.


What is the thought process behind him using the term "witness"? I can tell it is backed by an interesting perspective and I'd like to learn more about that perspective.

At one point, he said this witness "proved" something ... so is this coming from "propositions as types"?


The use of the term "witness" here comes from constructive logic, where proofs of propositions have actual computational content. There "witness" means the same thing as "proof" but is more evocative that the proof is data that can actually be manipulated.

You might like this article if you're interested to learn more: http://jozefg.bitbucket.org/posts/2015-01-09-constructivism....


Ah, I found it: https://wiki.haskell.org/Type_witness

In my own words, a "type witness" is a Haskell idiom (maybe broader?) that allows you to perform dynamic casts.

Here's the first example from that link:

A simple witness type might be defined over the Int, Bool and Char types like so:

data Witness a where IntWitness :: Witness Int BoolWitness :: Witness Bool CharWitness :: Witness Char

dynamicCast IntWitness IntWitness pa = Just pa

dynamicCast BoolWitness BoolWitness pa = Just pa

dynamicCast CharWitness CharWitness pa = Just pa

dynamicCast _ _ _ = Nothing


> [119 people] Of whom, we can assume the majority are web-programmers, and, by association, that Elm’s is likely the strongest type-system to which they have been exposed.

No.


Does the same criticism apply to OCaml and F#? Anyone who used these languages for long time, how do you solve lack of higher-kinded types (or OCaml has them?) and do polymorphism?


I don't really agree with the premise that not having type classes is as big of a problem that the author thinks, but to answer your question OCaml has functors which are basically higher order modules. A functor in OCaml is a module defined over abstract types and you instantiate it with concrete types.

A lot of people in the Haskell community have yearned for this as well, and the latest version of the Haskell compiler will support something similar called Backpack.


In F# you can always bail on the strict parts of the F# type system and use .NET classes and interfaces for polymorphism.


A few months ago, I spent a few evenings trying both Elm and Purescript. Elm was easier to get started with, but felt much more cramped and difficult to scale up to large programs. Purescript was more complicated to figure out (I had to read about F-algebras to understand Halogen's UI query algebras), but it's substantially more powerful and flexible. It's very similar to Haskell, with the addition of built-in record types.


In cases where we're "acting on" some value, like a dictionary, surely we should be able to store the comparison function in the value? I don't know Elm, but something like the following Haskell:

    data Dict k v = D (k -> k -> Bool) [(k, v)]

    empty :: (k -> k -> Bool) -> Dict k v
    empty f = D f []

    -- and so on
Of course, this is a naive linear-time implementation; substitute with whatever alternative you like. If you already have some type-level "comparable" thingy, you can make an "emptyFromComparable" to pre-populate with the built-in compare function.

We could do the same for things like Set too.

As far as I can see, the only 'problem' would be operations like `merge`, where we might have two different functions. The simplest thing would be to bias in favour of one, e.g. turning `merge d1 d2` into something like `extendWith d1 d2`.

I'm not saying this can replace typeclasses or modules in general, but in these sorts of cases we're already passing around a datastructure, so why bother passing around the required functions separately?

There's probably some irony here, considering the fact that GHC implements typeclasses using dictionary passing!


http://package.elm-lang.org/packages/eeue56/elm-all-dict/2.0... is an example of a Dict where you pass in a custom (key -> comparable) function when initializing the datastructure.


My reaction to this is mainly that typeclasses seems annoying to use in the first place, and that the alternative seems, if anything, even more annoying.


I wish Even had chosen a different name for his project. Elm is (was) a popular text-based e-mail client for Unix/Linux systems. See: https://en.wikipedia.org/wiki/Elm_(email_client) I still sometimes use it while shelled into a remote system.


What's a good alternative to Elm?


For nearly half a decade, you have been able to compile OCaml[0] to JavaScript with js_of_ocaml[1]. For a comparison of writing native bindings for both Elm and OCaml (and some TodoMVC code that uses them), check out elm-d3[2], and ocaml-d3[3]. elm-d3 predates the virtual-dom library and was therefore the first Elm library to provide a direct interface to HTML. It also predates the removal of signals in 0.18, so it needs to be ported. Been having some difficulty with that. I've had the native code blessing to publish it for a couple years, but never have.

[0]: http://ocaml.org/

[1]: http://ocsigen.org/js_of_ocaml/

[2]: https://github.com/seliopou/elm-d3

[3]: https://github.com/seliopou/ocaml-d3


Language wise scala.js[1] with cats[2] or scalaz[3]. The FRP story there is unfortunately more complicated.

1| https://www.scala-js.org/ 2| http://typelevel.org/cats/ 3| http://scalaz.github.io/scalaz/


You can go with the Diode [1] library for an Elm/Redux-like architecture. And with that you don't need to all the way down to cats or scalaz (although you sure always can if you want to).

[1] https://github.com/ochrons/diode


Take two average JS programmers. Hand one of them the Elm docs, the other the Diode docs. What do you expect will happen?


Both will continue using typescript/redux/react combo. Scala.js mostly makes sense if you are already familiar with scala, that's hardly surprising.


Depends on what you're looking for. Keep in mind that the OP came to Elm with a Haskell mindset. Elm is simpler than Haskell (yes, at the cost of some boilerplate).

If you program in JavaScript and you want a language with no runtime exceptions, go for Elm. If you want type classes, go for PureScript.


I don't know if it is good, but there is http://www.purescript.org/

Maybe look into https://github.com/clojure/clojurescript ?



Eve looks like it is filling the same sort of role: http://programming.witheve.com


PureScript, BuckleScript, and GHCJS, are all good options depending on your risk sensitivity and lang preference.


JavaScript?


> Ord a is a witness that type a is well-ordered, which is to say that for any two as, one is definitely less than or equal to another.

What the author described here is a linear order, not a well ordering, despite linking to the correct Wikipedia page.


tl;dr static typing adds lots of complexity to everything, just use Clojurescript instead.

Ok, I'm jesting. And I like static typing. But sometimes it is easy to get lost in it when you just want to be productive instead.


As I noted in my comment: Clojure and Clojurescript now have a far superior instrument than static types, it has `Clojure.spec`


I'm keen to hear more about the guitar learning helper you guys built! I've been planning to build a similar thing for a little while now. Care to do a blog post on what you guys did?


Evan needs an EXT set of libraries for stuff not in core just like Matz did. My pain point is forms. Make form generation and client side validation easy and everything else will follow.


OP should try do build a better framework/language, then.


This might seem like a silly question, but what would happen if you tried to use the same kind of system, but with another language?


What do you mean by "system"? The post talks about how other languages solve the problem, e.g. typeclasses, or emulating them with classes.


What do you mean by "same kind of system"?


Unfortunately this is an opinionated piece with foul language and it is a bit offensive. Sandy should take into account that Elm is created by one person pretty much (‎Evan Czaplicki) who created it in his PhD thesis and has been maintaining it since. So it's someones baby still, and they might be offended.

It is a remarkable for one person to create a language, runtime, repl, debugger, compiler to another quirky language i.e. JS that is usable to the point that people are doing professional work in Elm. Also the compiler produces easy to understand messages.

Evan has made Functional reactive programming more accessible. I don't think I would have a chance to understand FRP at all without Elm. Elm has inspired other frameworks in Purescript and the development of ReactJS.

Sure Elm is not perfect. I found that much of the JS ecosystem not viable in the Elm world, even with FFI due to the purity of the virtual dom. I can't just go and easily chuck an impure calendar control in my code.

However despite it's drawbacks I feel the article was a bit strong in putting down Elm, which is sad because I think there are the seeds of some great future languages and ideas in there.


I think it's valid criticism. There's a (excruciating) description of a use case, (valid) attempts to build a solution, and reaching the point where someone tells you "No, you can't have that because I don't want to" - whoever that may be - is understandably frustrating.

Especially when the facility in question solves a real PITA of a problem.

Now, the author was obviously venting, he even admits it. Nonetheless, the complaint is justified.


I don't think the response was as simple as "No, you can't have that because I don't want to". Reading the discussion about removal of this feature on Github there seems to be a few more points made that the author alludes to: https://github.com/elm-lang/elm-compiler/issues/985

Also, It's worth noting that Elm does have a BDFL. Evan makes the call and, as I'm sure a lot of python folks would agree, that setup means that the language is going to remain consistent, clean and well defined. This might be frustrating, but is part of keeping a strong design philosophy that directs the language. In that context, is it really a valid criticism?

Evan actually addresses this issue directly by talking about the different communities with different aims. He says that having these different communities with different design decisions makes the whole scene a lot stronger[1]:

> if you go back a year so on the mailing list you'll see a lot of people talking about type classes "when are we going to have this in Elm?", "we need this", "this is the most important thing", and a language came out that had different priorities and all the people who wanted that kind of feature started using that language and so now that's not to say one of the communities is making a better choice than the other, it just means we can all experiment with a different philosophy and way of thinking and do well."

[1] https://youtu.be/DSjbTC-hvqQ?t=178


It was exactly one comment from evancz, which says: "I don't want to readd this feature...I think it makes sense to continue discussion in this issue if you think there are valid use cases". Here [1] is the actual feature request.

The existence of a BDFL is irrelevant. This rejection is frustrating whether it comes from one person, or a committee, a peer, whatever, because it is arbitrary and unjustified. The feature wouldn't compromise the design philosophy nor its consistency. "I don't want this" is not a design philosophy, and neither is "your use case is invalid".

The use case is actually solid. Writing readable, maintainable code which is conceptually easy to understand in the span of a few paragraphs, like in the blog post.

[1] https://github.com/elm-lang/elm-compiler/issues/1283

PS. I'm certain evancz has a reasoning behind his wish to keep the feature out of Elm. He just doesn't communicate it, which makes the decision seem arbitrary.


When he removed the feature it was after consulting the community (https://github.com/elm-lang/elm-compiler/issues/985).


Many languages with "BDFL"s have many contributors to core functionality. Elm does not seem to. For open source projects, that's pretty much a death sentence: although I appreciate Evan going off and solving hard problems with beautiful solutions, he can't do all the major work alone and expect to have a healthy, growing, open source project.


It has a dictator for life, but given the article doesn't seem like the B is earned yet :P


The "B" is never earned. In OSS it's usually as ironic as the "D".


Yeah I read this a few weeks ago and was similarly put off. I will give him one thing: it got me to start thinking about what I wanted in a functional language that compiles into JS, which ultimately steered me towards Purescript.

I think fundamentally he's correct, but the point that he is missing is the intended audience of Elm. He was not it. Elm is much easier to grasp than Purescript, for instance. There is less complicated syntax and there are less complicated features. I would would be quite happy to use it in a team that isn't familiar with FP and who wanted to use it for front end code. In fact, although I have yet to do a large project with it, I might even lean toward Elm over JS/CS and React. It just seems a lot more straight forward, with less options available for hanging yourself.

But, like I said, generally I agree with him wrt a general programming language. Purescript is a much better fit for that. I thought about trying to write some Elm code on server side, but it just seems like putting a square peg in a round hole. Also, having played with it, the code generation in Purescript seems really, really good. I have no trouble envisioning what it's going to generate for me, which I like.


> it got me to start thinking about what I wanted in a functional language that compiles into JS

I investigated Elm just after the 0.17 release, decided I was fine with it but didn't really love the language. I've since moved to investigating F# and the Fable compiler. While it's unlikely that someone who prefers Purescript would prefer an ML derivative, I feel I should mention it for other people reading the thread from the front page and prefer having imperative escape hatches.

The Ocaml to JS compilers (Bucklescript/js_of_ocaml) also produce nice js output but my background with Clojure has left me enjoying the benefits of being a functional language that's part of a larger ecosystem and I'm comfortable enough with .net core to be willing to treat F# as a viable language outside windows.


Can I ask if you have found any equivalent to the Elm Architecture in Purescript?

I have looked at Elm, and Purescript and now Bucklescript, but I have not yet seen, or wired up myself, something like the Elm architecture.

I should probably buckle down and learn the wiring I need myself, but I have been finding the typing a little tough.



Purescript Pux looks to be what you're looking for https://github.com/alexmingoia/purescript-pux/



I agree with most of this, but I beg to differ with the last bit :

> [writing] some Elm code on server side [...] just seems like putting a square peg in a round hole

We are actually writing server-side elm for a living. We mostly have a Scala background and we actually think elm is a pretty great fit for backend code.

Agreed, the absence of typeclasses is a limitation of the language. Yes, it means, you can't have a `Set RandomObject` or `Dict RandomObject SomethingElse` (among other things) and that can get pretty frustrating for folks coming from almost any other strongly typed language.

However the real question here is not "is this language worthless because of that", but rather "can I overcome that limitation for my specific use case ?".

My personal take : - If you are considering a switch from JS to elm (server or client), the point seems moot, as the language features described here are far from being available in JS. - elm suits _some_ server side application very well. Not _all_ server side application.


Point of information, it's an undergrad thesis[0], not a PhD thesis. Most of the language is now unrecognizable from that, with the original graphics library residing in this seemingly mothballed repository[1].

[0]: https://www.seas.harvard.edu/sites/default/files/files/archi...

[1]: https://github.com/evancz/elm-graphics


   Elm has inspired ... the development of ReactJS
I don't think that's true. React is a descendant of XHP, and predates Elm. Perhaps you were thinking of Redux?


ReactJS introduced virtual DOM before Elm did (Elm first used virtual-dom a lib that was developped quite some time after the release of react, and now uses a new custom implementation) redux was inspired by the "Elm architecture" where everything is global but composed by object/record keys at all levels of the tree.


Elm's virtual dom was inspired by Clojurescript's om, which was based off of React. So yeah, this is not true.


I've been writing in Clojurescript. To be honest - every time I see a new discussion thread about something new in Javascript-land I can't stop thinking that Clojure and Clojurescript are almost always a few steps ahead of the crowd.


Used to write in clojure and clojurescript myself. While it's definetly nicer than React, React did come first (om and reagent are just bindings around React. The way om and reagent are faster than React out of the box, is what inspired Elm's vdom module).


BTW, why lots of people think it's very wrong and immoral to criticize inanimate pieces of technology in rude and offensive language? Political correctness?


Whenever you feel the urge to use, or see others using the term political correctness, try mentally substituting it with behaving respectfully. The exercise can be enlightening.


That doesn't seem like a useful exercise because political correctness does not always equate to behaving respectfully, even if there is overlap (i.e. most respectful behaviour is politically correct and vice versa).

I could just as well suggest you mentally substitute the phrase helping the needy with kicking puppies whenever you encounter it.


political correctness does not always equate to behaving respectfully

Could you provide an example of when it doesn't?


For example, mocking masculinity/men, white people, Conservative people, etc is all "politically correct". I would not call it respectful to call Trump voters deplorables or to belittle issues that men face, but it's certainly not politically incorrect.


I think I see what you mean, but in my experience, this is not how most people understand or use that term. Wikipedia backs me up on this:

The term political correctness (…) in modern usage, is used to describe language, policies, or measures that are intended primarily not to offend or disadvantage any particular group of people in society.


"safe spaces" in Universities.


I see no use of the term political correctness.


I can't speak for it being immoral, but basically, using rude and offensive language tends to undermine rational discourse. If your purpose is get at the truth, then it is prudent to avoid such language.

However, a lot of writing (academic, journalistic, what have you) has "getting at the truth" as only one of its goals among many, including "expressing my feelings," "attacking someone else," "playing with poetic language," "sounding smart," etc.


There are people on the other end of the screen who built the technology, and they have feelings :)

Being nice is good.


And being polite ("nice") makes it more likely that people who don't yet know each other well will receive mutual advantage through collaboration.


someone posted this to HN the other day https://wiki.lesswrong.com/wiki/Crocker%27s_rules .. I thought it was quite good, it means sometimes articles like this, with their emotional language gives you information that is useful... IF you refuse to take offense to it.


Yes. Generally, tone policing in HN gets stronger with the passage of time. Many comments in here complain about the tone without even touching on the point.


Here's how I see his point.

He came to Elm expecting a Haskell for the web. Elm has the completely opposite philosophy of keeping things simple, even if it means extra boilerplate.

I can understand OP's frustration, but if he watched a few of Evan's talks (like this one https://www.youtube.com/watch?v=DSjbTC-hvqQ), he would realise his expectations about Elm are wrong. Also, he forgot that Elm (just like any other open source project) doesn't owe him anything. That's why many people take an issue with his tone.

In summary, Elm's target audience are JavaScript developers. It's developers who want their apps to be more robust and easier to refactor than in plain JavaScript. Sure, type classes are useful but they also increase complexity. Evan wants to see if there's a better solution and the Elm community generally accepts that.


> Also, he forgot that Elm (just like any other open source project) doesn't owe him anything. That's why many people take an issue with his tone.

We can't take issue with his tone by appropriating information about Elm's direction in an ex post facto manner. The guy - whatever guy - is a newcomer to Elm, picks it up, see an obvious deficiency, asks (quite politely, I might add) about a feature addition, gets a dismissive answer. That's the context. We can't apply Evan's* rationale behind the reply here, because the OP never had the chance to have it revealed to him to the extent of his interaction.

I'm surprised I have to point this stuff out. However understanding we may be, surely we can see why anybody is frustrated with being dismissed like this?

* Apologies, but I don't actually know Elm's author's last name.


As I said in my post, I understand OP's frustration. I understand that he expected more consideration for his efforts to learn the language and his suggestions for improvement.

The deficiency was only in his eyes though. Evan and the Elm community are fully aware of the type classes thing, because it's been mentioned by many people. He just doesn't see it as something that requires an immediate solution.

To summarize: I understand OP's frustration. At the same time, Elm (just like any other open source project) doesn't owe him anything. If you open a pull request or an issue you are not guaranteed a resolution in your favor. Ranting will help you vent but that's it.


Is Elm open source? If so, couldn't the author implement the feature themselves? If the maintainer doesn't want it, then idk, fuck off? Nobody said he had to use it. When did open source turn into "Do whatever random people tell you to do, for free"? Talk about entitlement....


> Is Elm open source? If so, couldn't the author implement the feature themselves?

Yeah!

Just create and maintain your own damn dialect of a language!

It's OPEN SOURCE, that means you automatically know and are an expert in anything it involves!

It's 2016, we can stop with that meme now.


> He came to Elm expecting a Haskell for the web

No, I don't think that's true. He came to Elm hoping there would be some useful ways to create abstractions in the language (that doesn't necessarily mean there has to be typeclasses. in fact, the whole article his him pursuing an alternate method of abstraction), and besides creating a function there really is none in Elm.

You must resign yourself to write the same boilerplate over and over. It is impossible to keep any large Elm project DRY.


and who cares? fork the project and add the feature yourself. when I buy banana yogurts at the supermarket, I don't write to the yogurt company asking to change the flavour if I don't like it. I just buy a different brand of yogurt. Elm is even free as in free beer and free speech!


There is a limited interaction between yogurt buyers and yogurt makers that solely consists of buying or not buying stuff. There is more interaction between programming language creators and programmers and indeed between programmers about their tools.

Analysis in depth is a useful thing for not only the creator who is likely to already understand the trade offs he has made but for other current and potential users of the language.


> Many comments in here complain about the tone without even touching on the point.

Then we'll either have to change all those commentators, or the original author – since one of the arguments against faul language is that it distracts.


"Evan has made Functional reactive programming more accessible."

Agree. [0]

[0] Substitute FRP for Subscriptions ~ http://elm-lang.org/blog/farewell-to-frp


> I can't just go and easily chuck an impure calendar control in my code.

Actually, you can... as long as you properly isolate the control. Here is a prof of concept that does just that:

https://github.com/fredcy/elm-polymer-calendar


This is no judgement on Elm as I have not used it.

I feel like RxJS and Cycle.js both make functional reactive programming quite accessible to JavaScript developers without the burdensome overhead of an entirely new language for the frontend.

Have you used these frameworks, and if so could you articulate why Elm would be a better alternative?


> Elm has inspired other frameworks in Purescript and the development of ReactJS

Can you give a few examples? Google is not being helpful.


One that comes to mind (for Purescript) are the error messages.


> Unfortunately this is an opinionated piece with foul language and it is a bit offensive.

Whenever you read "X is offensive", mentally replace it with "I find X offensive". The substitution emphasizes how little being offended ought to matter.

Your finding this piece offensive does not create an obligation on the part of anyone else. I am growing very tired of social critics attempting to turn the world into inoffensive mush. We need more articles of this kind.

> It is a remarkable for one person to create a language, runtime, repl, debugger, compiler to another quirky language

I agree that the effort is remarkable. The idea that the strength of the author's effort should somehow shield his work from criticism is antithetical to excellence. It's participation trophy culture. If we're to create great work, we have to understand the difference between good and bad work, and we can't do that if misplaced concern for someone's feelings stops our describing reality as it is.


Sandy is wrong.


Yeah, well, you know that's just like ahh, your opinion, man.


Leo Tolstoy on War and Peace:

"I decided to write a detailed story about events surrounding the French invasion of Russia, and the impact of the Napoleonic era on Tsarist society, as seen through the eyes of five Russian aristocratic families; since I haven't used the language before, for kicks I decided to do it in Swahili. This blog post will summarize why I hate Swahili and why it's totally unsuitable for writing about Tsarist Russian society - or, I would say, anything else. Swahili is awful and needs to die."

Seriously, how can people write blog posts like this? You decided to code up a new project in a totally new language, and are here to tell us why that new language is awful. Really? Really? It's not like this is uncommon. People make these blog posts all the time! What's with this?

-------------------

EDIT: I got downvoted, but look:

>A few weeks ago, on a whim my friend and I decided to hackathon our way through an app to help us learn how to play guitar. In a stroke of inspiration, we decided to learn something new, and do the project in the Elm programming language, about which I had heard many good things.

>Consider this post to be what I wished I knew about Elm before deciding to write code in it. Since I can’t send this information into the past and save myself a few weeks of frustration, it’s too late for me, but perhaps you, gentle reader, can avoid this egregious tarpit of a language where abstraction goes to die."

It doesn't take "a few weeks" to learn a programming language!!!


> It doesn't take "a few weeks" to learn a programming language!!!

No, it doesn't. It takes a few hours.

Which, I'm sure sounds flippant, but hear me out. In the 25-30 years I've been a professional programmer, I've been paid to use many different languages. FORTH, Fortran, C, C++, Pascal, Protel, C#, Java, Perl, Ruby, Go, Javascript/Coffeescript, and Python are the ones that come off the top of my head, but if I were to go through my CV, I'd definitely remember a few more.

Anyone who has programmed in a handful of the above will notice that (with the exception of FORTH) these languages are practically identical. They all have slightly different features and slightly different syntax, but once you know one, you can pick up another one pretty easily. Especially once you know 5 or 6 of them, you practically don't even need to look at the docs. Just glance at some example code and you are on your way.

Libraries and frameworks take a lot more time than languages. There are lots of crazy details that you have to remember. Luckily, most of the major languages of the same type have very similar base libraries. As long as you stay away from frameworks, you can be productive pretty much immediately. Learning the details can take a few weeks, but mostly its unimportant. Frameworks suck. I've been working in Rails on and off for... 4 years???? I'll never put that damn thing on my CV. I still don't understand how it works.

So, I don't know this author, but he is clearly knowledgeable in Haskell. Maybe he also knows Ocaml. It would take you about 15 seconds to pick up Elm from that background. The rest is discovering (and apparently complaining) about the bits that don't live up to your expectations. He didn't comment on the state of the libraries (except to complain about the political process for getting libraries distributed with the official tools).

I'm not going to defend his rant. I didn't enjoy the tone and I think he completely misses the point of why the language is there. But his technical complaints are perfectly reasonable.

I didn't vote you down, but I suspect the reason other people did is that you are a bit too quick to criticise the author's ability to accurately judge the language. He seems perfectly capable, even if I disagree with his conclusions and his tone.


So my point was actually about the specifics of picking up a language to do a new project, and then complaining about it. (Hence my example of writing a serious book in a language you don't know.)

I think you really go into superlatives here. It's not fair for you to say "15 seconds", for example. 15 seconds is how long you've been reading this comment.

(I just timed myself, okay maybe 10-13 seconds.)

I also think that "a few hours" is an exaggeration on your part. Let's pick a language you've never used - take Objective-C which is similar to C# and C, C++ which you've already listed, and I think you've never programmed in it, because if you had you would probably have listed it.

Okay, so now make a serious iOS app in Objective-C in "a few hours". As in, have one by this time tomorrow. See? It's crazy. That's not how it works.

Maybe the weeks and months and decades run together for you, but there is a huge difference between doing something for a few months or a year, or doing something for a couple of weeks as our author reports. I don't like his kind of blog posts, and it is a whole category - there is this whole type of blog post where you pick something you've never used, use it to do something new, and then complain about it, all within the space of your first week or two using it.

It strikes me as kind of ridiculous. Especially with a provocative title like "Elm is wrong." Literally, it's like Tolstoy writing War and Peace in Swahili, a language he didn't know, and then writing a blog post "Swahili is wrong" -- all within the space of two weeks of when he first learned Swahili. I might be exaggerating slightly, but I think my analogy holds. It's almost farcical.


You seem to miss the point.

Elm is particularly easy to pick up for people coming from Haskell. Maybe not in 15 seconds, but 15 minutes is a totally reasonable estimate.

The author can without doubt write a large project in Elm. His complaints were about missing the conveniences of abstraction Haskell-like languages provide, and he is more than qualified to talk about it.

Decomposing records into tuples of comparables has probably crossed his mind :)


>15 minutes is a totally reasonable estimate [coming from Haskell]. The author can without doubt write a large project in Elm.

Well, all right. In general I would say that is not true even for languages that are close, but there are exceptions and I suppose I can take your word for it.


It's only because Elm is basic Haskell minus a lot of stuff. So basically if you know Haskell you already know Elm (so you need the 15 minutes to get up to speed wrt ports and subscriptions or whatever), but at the same time miss the stuff that has been left out that you take for granted, hence the failed attempt of the author to get some of that back.


That could have been presented much more clearly in the article.

It would be interesting to compare with the opinion/experience of someone who didn't know Haskell, well, right? (Though in that case perhaps the learning curve is too steep, maybe Elm isn't meant for that.)


Actually, that's the thing: Elm is designed for people who don't know Haskell. It's designed for JavaScript developers who are attracted by the "no runtime exceptions" claim.

If you're coming from Haskell, you'll see Elm as a dumbed down, stripped version of Haskell, which will trigger in you the feelings it triggered in the OP.


Thanks. The chances we'll hear the perspective from a javascript dev with no haskell exp are slim though.


Join the Slack elm channel. You'll find them there.


> Okay, so now make a serious iOS app in Objective-C in "a few hours". As in, have one by this time tomorrow. See? It's crazy. That's not how it works.

But then making an iOS app requires picking up frameworks/libraries, not only learning Objective C, which was exactly GP's point:

>> Libraries and frameworks take a lot more time than languages.


From the article:

"Unfortunately, Elm isn’t a library. It’s a language, which just happens to have a great library"

I don't know why we're arguing about this. It's another blog poster writing about something new they tried for one particular project, and in this case literally "why it's wrong". (After two weeks.) It's hard to take seriously.


I find that there are times where I get into a "Someone is wrong on the internet" situation, but still think it's worth commenting. This is one of those times. My goal is not to win the argument, but rather I hope I can show you a different way to look at the situation. To be fair, the only reason I wrote my original reply to you was because you asked why people would down vote you.

Clearly 15 seconds is unreasonable, and in retrospect I regret having written that. As I am trying to convey what a reasonable amount of time is to understand a language, using unreasonable numbers is unhelpful.

From my experience, if you were to give me a legacy Objective-C application and ask me to fix a bug in it, it would take me much less than an hour to understand what I need to know to fix that bug. It would literally take me seconds to understand the syntax well enough to read the code, only being slowed down occasionally to look up syntax that I didn't understand. (To be fair, I have already fixed many bugs in Objective-C programs before, so I know exactly how long it took me -- despite not "knowing" the language at all).

If you asked me to write an Objective-C program from scratch, it would take me 10-20 minutes to get started. My main problem would be in choosing appropriate libraries. For example, I like to TDD, so finding a good test library would take me some time (though I can live with XUnit and the chances that there isn't one for Objective-C approaches zero).

If you ask me to make an iOS application, it would take me at least 1 day, probably 2, to get set up and start writing code. This, of course, has nothing to do with Objective-C and everything to do with figuring out how to get the build system working, etc.

It would take me at least a week to get to a point where I'm writing idiomatic Objective-C for iOS apps. It depends on how much code I could find on the internet. Free software is great for this, but there is precious little for iOS (in comparison to other platforms). On the other hand, if you asked me to write a GNUStep app, it would be much easier.

It would take me years before I was actually knowledgeable about iOS. No, scratch that. It would never happen. I have absolutely no interest in becoming an expert in iOS.

But let's back up here. How much knowledge would I need to have to critique Objective-C as a language. Again, I urge you to read the original blog post closely. The author opines that Elm is fundamentally broken as a strongly typed FP language because it doesn't have type classes. This is what he says is "wrong" about Elm.

He is correct. There are no two ways about it.

Now we can argue all we like about how Elm programmers can work around this deficiency. I think he's missing the point that Elm is aimed at programmers who do not want to deal with the complexity of a fully featured strongly type FP language. We can debate about how front end programmers (the likely target for Elm) will rarely run into situations where they absolutely need type classes... But he's correct in his statement.

He's expressed his opinion in an offensive way and he's turned a blind eye to the fact that people can still enjoy many of the benefits of the language, even with this obvious problem. But he has not made an error in his analysis.

And he didn't need weeks to discover this. It's very clearly stated in the tutorial. He could have saved himself weeks and read the damn thing. It would have taken him 20 minutes. And then he could write the same offensive piece and still not be wrong.

The reason I'm pointing this out is that it is beneficial as a programmer to realise what is easy and what is hard. Many young programmers (that is to say, programmers who have written only a few thousand or a few tens of thousand lines of code), conflate frameworks with languages. It's easy to miss the distinction between the features of a language and the features of a framework.

Why is it important? Because if you understand the features of a language it will serve you well going forward. There are only a few categories of languages in the world. Everything is just a different spin on that category of language. If you learn a few examples for each category, you will never have trouble finding work in your career. It will take you hours to jump from one environment to the next. I'm nearly 50. That's why I'm still employed.

But on the other hand, frameworks and libraries have endless variations. And you absolutely must understand certain details or else you will be in for a world of hurt in the future. The downside, though, is that the framework/library will give you no benefit at all when it is dead and buried. How many DB2 programmers did I go to school with that are useless today? How many MVC programmers did I work with that are useless today? .NET, iOS, Android, PHP, Rails, insert-flavour-of-the-moth-here. Before you are finished your career, they will all be gone (or good-as in terms of furnishing you a living wage).

The author seems well qualified to make the statements he makes. He does so obnoxiously, but obnoxious != wrong. He's spent much more than the amount of time he needed to come to his conclusions.

I get the fact that you hated his blog post (and that you hate obnoxious know-it-all blog posts in general). I hope I have convinced you to take another look and understand the distinction between what he's trying to say and what you thought he was saying. There is a lot of valuable stuff in there. Even if it is obnoxious.


So is it fair to say that it is possible for me to conclude "xyz is broken" based on a single paragraph? For example, if I read the Wikipedia article on Perl 6, the second paragraph says "While historically several interpreter and compiler implementations were being written, today only the Rakudo Perl implementation is in active development."

So let me skip the part where I spend 2 weeks picking up a language!

Let's go straight to: "if an ostensibly open language only has one single implementation, it is fundamentally broken and underspecified and should not be used by anyone, period."

Is the part I quoted enough for me to conclucde that it's a broken language not fit for any use by anyone? Because the article that we're talking about has the title "Elm is wrong."

Can I say, "Perl 6 is wrong" without even bothering with coding in it for a few months?


"Elm is Wrong" is a good click-baity title. It's not out-right lying, but opinionated sure. It leads me to want to know in what way it's "Wrong", somehow broken fundamentals, stupid API, bad implementation, or what have you.

Given the response in this thread, I can only surmise it was a well chosen title for a blog post.


But HN has an explicit policy against clickbait titles, and usually edits them to be more descriptive.


Having a single implementation is quite a different situation than having a missing feature that most people would consider necessary.

A better example would be back in the old days perl had no intrinsic OO support. Instead it had a library that made a few things easier. But basically, the OO support was hashes that pointed to functions. There was no syntactic sugar at all.

As an OO language Perl was fundamentally broken. You could still write OO code in Perl (and I happily did so for a very long time). But, yes, there were many people who claimed that Perl should be avoided because of this. Eventually full OO support was added and those voices died down.

The difference between that situation and this situation is that the author of Elm (as I understand it) has absolutely no intention of adding type classes to Elm. He has specifically chosen not to have them because he thinks it complicates the language. I happen to think that for his target audience, he is absolutely right. I think it is a good decision.

However, for the author of the blog post, the decision is wrong. Elm is intentionally broken. The author does not want to fix it and the blog post author thinks that this decision is wrong.

He also complains about the maximum size of tuples. The author of Elm believes that you should only have small tuples because you should be using records instead. This is contrary to how FP languages tend to work. Usually you use tuples. Records are the strange structure to work with. Again, I agree with the author of Elm, but the author of the blog post has a completely valid point. In his opinion, Elm is wrong.

The author of the blog post found a way to get around several of the problems he was having with Elm, but it required him to add or remove fields in records. The author of Elm had disabled that feature because it was complicated. Given that doing this removes the only way the blog post author (and me too) has to work around the lack of type classes, he was upset. Even though I understand the blog post author's frustration, I agree with Elm's author. JS implementations are optimised for objects that don't change structure. Records are implemented with JS objects and so allowing the records to change structure will impact performance in ways that the Elm programmer won't expect. It's a pity, but shit happens. Of course the blog post author thinks this is wrong.

Finally, it's not like you are locked down here. You can easily write an extension in JS to fix the issues the blog post writer has. But the kicker is that JS extensions can not be distributed with the normal Elm tools without approval from Elm's author. And Elm's author has said that he doesn't want those things fixed. So even if you wrote a work around, you aren't allowed to distribute it.

So given all this, I hope you can see the blog post author's point. Elm is fundamentally broken. The Elm's author knows that is broken and refuses to fix it. The only way inside the language to work around the broken feature was removed and Elm's author doesn't care. You could fix the problem by writing an extension, but Elm's author has blocked that avenue as well. You are not allowed to fix this problem.

This is what he feels is wrong. I completely understand his point of view, even if I disagree with his conclusion. Your characterisation of the situation trivialises it. You assume that there is no way the blog post author can know what he is talking about because he hasn't used the language long enough. You haven't spent the time yourself to understand what the issue is and why the blog post author is upset. You just assume he is a dumb ass. That's why you were getting voted down.

I spent a lot of time trying to explain the situation to you, so I hope at some point you find it valuable (even if it doesn't seem so right now). Like I said, sometimes I get the impression that spending my time on things like this is worth it. In my past, some people have graciously spent similar efforts to help me understand something and eventually it was helpful to me. I hope that will be the case here.


I agree.

The post's tone is a bit harsh and could be more respectful. After all, there is no consensus for type classes, [ML's modules being an alternative](https://existentialtype.wordpress.com/2011/04/16/modules-mat...)

Nonetheless, the post is interesting and worth the reading because it raises true questions. For instance, I was surprised to learn that adding a field to an extensible record was no more a feature.




Applications are open for YC Winter 2020

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: