Hacker News new | past | comments | ask | show | jobs | submit login
A nice app on Elm street (madewithlove.be)
149 points by andreascreten 28 days ago | hide | past | web | favorite | 79 comments

For anyone new trying to get into Elm (as a language/tool), I would look elsewhere. ReasonML, PureScript, TypeScipt, etc are all better featured solutions. Having said that, the article is well written and thorough for anyone wanting to take a look into Elm.

But there are massive problems with Elm itself which make it impossible to consider seriously. I have and still do use Elm in production, and went through the nightmare upgrade from 0.18 to 0.19.

1. Elm ports are not sound. Elm will tell you everything is good but doesn't do simple checks - as say PureScript does - to see if your port code actually exists or adheres to the defined contract. There are other tree-shaking issues, but Elm does not know and does not care about the js you've written.

2. Evan holds the naive view that everything can be rewritten in pure Elm and there's no reason not to. An overwhelmingly common use-case is 3rd party services or tracking libraries where it's impossible to re-implement; these apparently don't exist.

3. Elm applications, without a Redux-style (domain-specific to Translator) pattern, end up being horrendous spaghetti code of everything knowing about everything. Cmds and Tasks are a pain to work with when they should be interoperable in some manner.

For small embeddable or personal projects Elm is a fun tool. I don't see it being more than that until more community involvement is permitted - removing the dictatorship.

Elm has solved big problems with us, and for everything that can run in the "pure Elm" side of things, we have very few problems.

> Evan holds the naive view that everything can be rewritten in pure Elm and there's no reason not to. An overwhelmingly common use-case is 3rd party services or tracking libraries where it's impossible to re-implement; these apparently don't exist.

He quite loudly holds the opposite view: instead of thinking you need to port everything to Elm (very common urge for newcomers), keep it in JS and use it over a port.

All the wording in https://discourse.elm-lang.org/t/native-code-in-0-19/826 seems to indicate the opposite. I'm not saying jQuery bindings are a good idea, but saying no to _everything_ b/c you don't want jQuery bindings is.

For what it's worth, PureScript is much more complex than Elm. I see people recommend it, but I don't see people actually use it nearly as much as Elm (not that Elm is super widely used, of course). I do agree that the biggest thing Elm needs is to open up development, break down the "dictatorship" as you put it, and accelerate the pace rapidly.

I think OCaml/ReasonML seems like the nicest choice, even if you're using the Elm architecture. Functors make it really easy to combine components, which actually makes it nicer than Elm for the same tasks.

Regarding #3, would you mind pointing out some good resources/examples that illustrate this pattern?

https://medium.com/@alex.lew/the-translator-pattern-a-model-... describes the pattern quite well in elm-first terms.

I am a back-end developer, and I don't know front-end. I also know very little of functional programming.

Elm is the only language that I like writing, and where I don't feel in a state of frustration when I write. It might have a lot of limitations, bu tit makes me happy. Given that our job is basically to be in a constant state of half broken code, this makes me a huge fan of the language.

    our job is basically to be in a constant state of half broken code
In my experience, Elm code is only ever in a state of "horribly broken, won't compile" or "works". Whether that's a bug or a feature depends on what I'm trying to do...

That's interesting. How does Elm statically know if the logic of your app is correct? Since I don't know Elm I'll use some pseudocode:

  if condition
Is Elm able to determine that this condition is flipped the wrong way?

Neither Elm, nor any language in the Typed FP family, can do that. What it can do is to prevent us from making clerical mistakes. That's the surprising thing I learned programming in Typed FP: we very rarely make logical mistakes. Our programs are all broken, make no mistake, but they are broken not because we accidentally swapped a conditional (logical mistake), but rather because we passed in data of the wrong shape (clerical mistake).

A common clerical mistake which Elm, Reason etc. prevents, is when we grab something from a list and pass it to another function. What if in a rare case it is possible that the element doesn't exist? A function deeper in the stack might crash, or if defensively built, substitute it with an empty value. Both could be wrong.

By providing more information about our data and our functions to the compiler, the compiler can ensure our code always follow those constraints. These constraints are often in our head when using dynamically typed languages, or even statically typed OO languages. Typed FP helps us make them explicit in code so the compiler can track it instead of we tiring ourselves mentally and making a mess of it.

Expanding slightly, Elm (as well as others in this family), can create structures that assert certain rules. In the case of a list being empty, you can also use ADTs to create nonempty version ala `type NonemptyList a = NonemptyList a (List a)` where it's impossible to construct without that first element even if the second list is empty. A lot of languages lack this sort of feature. Then you can go about your code knowing you neither have to handle empty nor write a bunch of tests because empty construction is impossible and this is enforced by the compiler.

Sometimes I wonder whether Alan Perlis would mock at us for being Bible salesmen for Typed FP languages.. yet it is such a quality-of-life upgrade and a thinking tool that it feels justified to shout from the rooftops :)

> These constraints are often in our head when using dynamically typed languages, or even statically typed OO languages.

I’m curious about this comment on statically typed OO languages. I work mainly with C# and don’t have much FP experience. Are you referring to exhaustive matching?

Edit: To clarify, I understand that C# compiler won’t prevent you from trying to access an element in an empty collection. What prevents you, in a typed FP language, from accessing head of an empty list?

Yes I was thinking of a couple of things, but most importantly the existence of null in the language. So functions either receive exactly the type they were looking for (which is better than dynamically typed), or a null (which never happens in a Typed FP language).

In OCaml, (List.hd []) throws an exception, which is not a desirably behaviour, so we mostly use a safer version of List.hd which would return an option type. This could be either "None" or "Some(value)". To operate on option types, we have to pattern match and handle both cases where the value could be either None or Some)

Exhaustive pattern matching is useful here, so is the very notion of variants. Without variants (or sum type / union type) we tend to leave domain concepts implicit in the codebase. While we can simulate variants with classes, it is too unwieldy to be used except for core domain concepts.

Got it, thanks!

Just want to give props. This is the clearest explanation of the value of typed FP I've ever seen.


> Neither Elm, nor any language in the Typed FP family, can do that.

I didn't think so. So claims like:

> In my experience, Elm code is only ever in a state of "horribly broken, won't compile" or "works".

Which I find to be pretty common among fans of strongly typed functional languages, is incorrect.

Elm makes no claims to correct your logic. Logical errors are not caught by the compiler. You might still decode a JSON field to the wrong field on a Record (if the fields are the same type), you might invert a BOOL and use True were you meant False, you might incorrectly calculate some value, etc.

But, state errors are caught – your application can not get into an impossible state and therefore should never have any runtime errors.

Getting back to logical errors – Elm can provide some additional safeguards. For example you could have a record

``` type alias Point = { x: Int, y: Int } ```

and then decode it with

``` decode.map2 Point (field "y" int) (field "x" int) ```

Whoops you got the wrong order.

So you could make X and Y explicit types:

``` type alias Point = { x: PointX, y: PointY } type PointX = PointX Int type PointY = PointY Int decode.map2 Point (field "x" decodeX) (field "y" decodeY) ```

Now your decoder won't compile unless the types line up correctly. But this adds a bit of extra overhead in unwrapping the values, but not much.

Yes, because in elm everything is pure. At least in the code you write. Elm will force you to declare all possible cases that can happen, all branches in every function you write. That leaves literally nothing to break.

Not saying you can't break an elm program. But you won't run into runtime exceptions in elm, by design:)

This has been my experience, 100%.

I love Elm, but this tutorial is based on Elm 0.18, and 0.19 is out. There are some straighforwared but significant changes with how an application is set up.

If you're just starting out, find a 0.19 tutorial.

T.b.h. this is the reason why I will probably stay messing around with either PureScript or ReasonML but stay away from Elm.

Why exactly? Elm 0.19 is out on August 2018, and the only thing that's expected is 0.19.1 which barely changes anything (doesn't break any api). Seems like 0.19 is quite settled at this point.

Ok, I should have said 'one of the reasons' ... and maybe there is a better road-map, but I was dabbling with Elm around 0.16, and then watched 0.17 change a bunch of stuff I liked to bunch of stuff I didn't care about as much and I decided to stay away for a while.

But if it looks like we would be on 0.19.x for few years to come, I might dip in it again ... it's not like I ever published anything in Purescript or ReasonML and I never used Elm in anger, so it is probably just a matter of time til I jump in again :)

Yes, frustration of people going through previous versions is definitely a thing! Let's recall not only the infamous drop of JS FFI (for Ports), but also things like ditching custom operators. Let's see how >0.19 will go.

Will my Elm code written today still be maintainable with an up-to-date elm environment in 3 years? It certainly isn't the case with code written 3 years ago.

Doubtful, but possible. What is highly likely is there will be 1 or 2 upgrades between now and in 3 years. If history is any indicator these upgrades will be relatively painless.

The next upgrade, 0.19.1, will be completely backwards compatible.

By contrast, I have a 12K-line Clojurescript project from 6 years ago that interfaces with React and still compiles and runs beautifully, even if I update the Clojure language version to the current version.

I agree this is a problem, but what "JavaScript" compiler/language technology isn't changing rapidly? 3 years ago we were using JQuery.

Yeah, I balked at changing my apps to be 0.19 compatible. Now I'm kind of just "getting along" with 0.18 until I can do more of my front end work in Phoenix LiveView.

We have a 100 kloc Elm application and the upgrade process was quick. Tracking Elm releases is considerably easier than the JavaScript ecosystem.

Complaining about unstableness, while chasing fads. Thoughts and prayers are with you ;)

In my experience this has not been a problem. First upgrades are very infrequent. Second, they occur for very good reasons. Third there is tooling to handle a lot of the code migration. Fourthly, the compiler will help you fix the rest. Lastly, each new version has been a real improvement on the previous.

I've been lurking Elm for a while, and with Elm 18 came to the conclusion that I should avoid it, because there was a single creator who simply could not keep up, and was uninterested in fostering a healthy community of contributors.

With Elm 19, I changed my mind. A closer following of the community shows that Evan is (a) nice, and (b) interested in contributions, but mostly in a researchy way. More importantly, Elm 19 seemed (to me) to tip the balance in usefulness and cleanliness.

And with the idea of taking Elm straight to WASM (and with WASI around), things are looking interesting in the (eventual… gosh but it moves slowly) future.

tl;dr: It's absolutely worth taking a new look at Elm 19.

Been working with Elm on so many projects the last 2-3 years. I don't think any other js-based framework can reach the benefits that Elm brings. Correct, readable and sane code at scale. And, like others said, makes front-end coding enjoyable and confident.

JS is a scripting language, good for small and quick scripts. Shouldn't be used for anything more than a few hundred LOC.

First time in a long time I actually enjoyed using front-end tech.

Elm sparks joy, similar to Ruby/Rails did back in the day <3.

Been working with Elm quite a lot. Every other web framework I've stumpled upon in my career appear like utter crap compared to this beauty.

I think the title should be edited. There is no section that combines Elm with React, it's mostly used for comparison.

You are right! I updated the title.

My own two cents worth on Elm.

I've worked with many languages, beginning with Fortran in my student days that I had to punch my own cards, then doing Basic, Pascal, C, C++, Python, Ruby, Javascript, Lisp, Scheme, some Haskell, not necessarily in that order. I've never had more fun and felt more productive than with Elm. The ability to do "extreme refactoring" and come out on the other side with everything working is liberating, exhilarating, and makes code maintainable and growable over the long term.

Been using it now for three years.

How does Elm compare to ReasonReact?

Oooh that's a very hard question :p I'd need to sit down a bit to answer it, to be honest it could almost be its own article. They both try to accomplish the same things through very different means with very different backings (Facebook versus literally one person).

I can already tell you that ReasonML definitely has my preference these days over Elm, for the simple fact that I can keep using React with it. I love React, it's one of my favorite frameworks. If you're already familiar with it you're 50% of the way there to learn ReasonReact, whereas with Elm it really lives in its own little universe that you need to get familiar with from scratch.

I find ReasonReact's underbelly a bit messier, and the compiler is not as good nor as clear as Elm's though. And the whole OCaml layer brings some chaos too, like the multiple standard libraries available in ReasonML (OCaml's, ReasonML's, etc) which can all be very confusing when you begin.

So, I wouldn't really know what to tell you, it depends wildly of your experience, what you like, what you're looking for in the language and so on. I'd definitely recommend to give both a shot and see what you like as they're both great languages to me, even if ReasonML has my preference.

> the compiler is not as good nor as clear as Elm's though

in the article, you mentioned:

> the compiler is one of the best compilers I’ve ever seen and will not compile if it detects that your code is not sound.

It seems like your're judging the entirety of the compiler just on it's user displayed error messages?

Indeed sorry that's badly worded, both compilers are very good, I meant more the UX around compilation in general as I'm not apt to judge the compilers themselves.

To me the biggest difference is that [Reason]React focuses on components which encapsulate state, while Elm focuses on data structures and pure stateless functions. Both approaches have pros and cons. You can design a [Reason]React app similar to an Elm app, if you use pure stateless components exclusively and handle your state with few reducers, but you won't get the same smooth experience which you get with Elm. I still favor React though. React's component interface adds some friction and complexity, but it's also a nice abstraction which helps a lot with code sharing, especially when sharing with third parties. Thus the striving ecosystem (UI frameworks, UI builders, etc.) in React.

I made a round trip over the last years from React/TS to Elm to ReasonReact back to React/TS. React/TS is the least attractive, but it's the one I get most done with. Plus the situation in React has gotten much better since Hooks, PureComponents, Context API. I'm glad the mess with class components is finally over.

I like Elm as a language, but the community is extremely toxic, and it's not production-ready yet (version < 1.0, one-person project). Too bad, because it's a great project.

How is it toxic? All the comms I've read from Evan were pretty polite.

> not production ready (version < 1.0, one-person project)

This is FUD. Elm is being used pretty successfully in production.

This is not FUD. Using it in production is a risky bet. And I say that as someon using Elm in production. We use it in a short-term, demo project. The project was started using version 0.18. Now we're stuck, either we rewrite huge parts of the app (and we don't have time for that), or we're stuck with older versions of the libs.

This is not something you can afford to do with a long-running, critical app, or at least you have to know you're taking some risks. It's a tradeoff.

Also, what would happen to Elm if the author suddenly died?

Many companies rely on Elm now it’s definitely production ready.

Anecdote to counter your anecdote: I don't find the Elm community to be toxic at all. Pretty much the opposite.

Great! That's a very subjective opinion anyway.

can you site some sources for the “extremely toxic” community? genuinely curious

richard feldman, evan's colleague, is not exactly a nice person on the internet. There are several times where he's ranted or had a temper tantrum for no particularly good reason.

now he alone does not make up the "community", but he's certainly a prominent member of it.

I've seen people banned from official forums because they disagreed with design decisions. And several threads locked with messages like "oh yeah, haha, we don't really want you to talk about that" (https://discourse.elm-lang.org/t/elm-0-19-released-what-has-... for instance)

And the github forum rules are a little "threatening" (https://github.com/elm/forum-rules/blob/master/README.md).

If I have time off to learn a new language in order to get a new Job, would Elm be a good choice?

I wonder if picking a niche language would give me an advantage or there would be too few jobs.

The biggest problem with elm in production right now is that there is no backward compatibility yet (version < 1.0). Code written in Elm 0.18 is not compatible with code written in Elm 0.19.

Too few opportunities, learn Typescript.

I'm curious if you know about the language I created - Mint (https://www.mint-lang.com)?

And if you do what is your impression? I created it because I was frustrated with Elm (more the community than the language itself although the language has some issues as well).

> But you will still hit regular road-blocks which learning it because of how alien some of its paradigms are when coming from Javascript.

I always found this to be a weird take. Elm is "Maybe Not As Good" because the average JavaScript developer isn't immediately familiar with it?

Maybe we should just be less averse to learning new things, and I don't think simple syntax swaps really count as new things.

Unrelated: your ToC doesn't work.

I didn't mean that only Javascript developers would be lost, more that Elm kind of "does its own thing" and as such some of its errors or mechanics can be a bit cryptic and require some more experience with the language.

It's not a language you can pick up and go as easily as Javascript is more what I meant, in my opinion at least unless, you're already familiar with pure and strictly typed languages.

I don't think Elm does its own thing. The ideas used in Elm are more "discovered" than "invented" (at least relative to JavaScript), if you're familiar with that line of thinking.

I also don't think its errors are cryptic. Elm's error messages are best in class.

> It's not a language you can pick up and go as easily as Javascript

I don't agree with this either. After having taught people Elm, and also JavaScript as a first language, I don't think mutability is more intuitive to a beginner.

Thanks for pointing out, will look at the ToC asap.

it’s a very valid choice when looking for Elm alternatives that have more backing at the moment

Are mere users still not allowed to interface with JS from Elm? I lost all interest when that came down.

Please don't spread lies about Elm. It's OK if it's too hard for you, or not your cup of tea.

But it's straightforward to interface JS from Elm. It's right in the tutorial under ports.

JS interop has never been an issue, it's publishing JS-interop packages which is gated[0]: port module is available in applications but not packages.

[0] formerly behind a review queue / review process to add to native-whitelist, now limited to two specific "core" organisations

We have a large Elm app and do the occasional bit of JS interop when required, it's not a problem at all.

The 0.19 change simply limited the ability to publish packages containing interop to the official Elm package repository. You can still host your own packages etc.

You mean ports and flags? It's described right in the tutorial : https://guide.elm-lang.org/interop/ports.html. I wouldn't call it not possible. It is necessary to have the cool stuff of Elm, unfortunately (or not).

It's not rocket science tough, and it allows for clean interfaces. I wrote about it just a couple ago ago : https://lengrand.fr/a-short-introduction-to-ports-and-flags-...

If you need your IO to be synchronous, then Elm is not for you.

Asynchronous IO through ports works just fine.

I don't think there will ever be a way to interface js directly from elm or vise versa. Ports are the only way.

Ha, OP meant directly? Well AFAIK that is simply not possible, to keep the purity of Elm programs. All has to go through the Elm architecture. Or am I mistaken?

Sorry for the late answer but yes it's not possible to keep elm's purity and safety while having a direct interface to js.

Every post on Hacker News regarding Elm the language inevitably includes this post about Elm the email client.

TBH this is the first time I've heard about Elm, the language. I was wondering why nobody else had made the joke, so I took a stab at it.

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