Compilers do not have the best reputation. Their intent is admirable: find sneaky bugs, help fix them, and generate fast code. Sounds pretty wonderful! The problem is that many compilers act like HAL 9000.

I mean, no compiler is literally a malevolent AI that wants to kill you, but sometimes it feels that way!

One of Elm’s goals is to change our relationship with compilers. Compilers should be assistants, not adversaries. A compiler should not just detect bugs, it should then help you understand why there is a bug. It should not berate you in a robot voice, it should give you specific hints that help you write better code. Ultimately, a compiler should make programming faster and more fun!

Well, today marks the release of Elm 0.16 which I think is a great step in this direction. This release:

Most importantly of these, Elm compiler is now producing the best error messages I have ever worked with. And I hope you will feel the same way!

Okay, enough overview, let’s dive into all the new stuff.

Note: Maybe you have seen better error messages? If so, tell us. Users’ reports of confusing error messages actually motivated most of the improvements in this release. We can only fix things if we know about them, so help us keep improving!

Mesh E Merrell Siren Hiking Hex Q2 Women's Vapor Boot qrwXIwp

In Elm 0.15.1 we took the first steps towards compiler errors for humans and asked the community to provide feedback in the error message catalog. Responding to this feedback has led to some extraordinarily nice error messages, so I want to highlight some of the user-reported issues that helped make this happen!

The Elm compiler now does type diffs where it compares any two types and highlights the differences. Notice that it hides information that is not directly relevant, so Richard just sees the fields that do not match. It even does typo detection for record fields, so there is a nice little hint pointing out the typo that caused the problem!

More Context

In previous releases, the compiler would only show you the part of the types that clashed. If we always showed the entire type, Richard’s problem with big records would have been even worse!

Zach Gotsch reported a nice minimal example of how this lack of context leads to confusing error messages. Well, thanks to type diffs it is not a big deal to show the entire problematic type and just highlight the part that is causing an issue:

Expected vs Actual

The most common question about type errors in Elm has long been “Why doesn’t it tell me which type was expected and which was actually given?” As you may have noticed in the previous examples, Elm 0.16 adds this information!

In the most basic example, you just get some information about what the function expects:

As I implemented this, I realized that this expected vs actual dichotomy does not really make sense in a lot of cases. A simple example of this is when the branches of an if do not match. Which is the expected one? Are they both actual? It just does not really make sense, so instead of settling for some convention, the compiler just “does the right thing” for each scenario. For example, when the branches of an if do not match it looks like this:

Beginner Hints

When you are starting out with a new language, there are a few things that you are pretty much guaranteed to run in to. Jessica Kerr is an excellent developer and speaker who recently got started with Elm, and she kindly reported all the times she ran into something weird. For example, when appending strings in Elm you use the (++) operator. Thanks to Jessica’s suggestion, Elm 0.16 gives a helpful hint when it sees folks trying to add strings.

There are quite a few others in there. Maybe you will see them when you install Elm and try it out ;)

No More Cascading Errors

You see “cascading errors” when one thing goes wrong, and then this initial wrongness leads to a bunch of other things going wrong. So with many compilers a single mistake can lead to 3 or 4 different error messages, leaving the programmer to figure out which one is the real problem.

Well, there are no more cascading errors in Elm 0.16 thanks to Hacker News! When we announced our first effort to improve Elm’s error messages, someone on Hacker News commented with a very simple yet specific description of s Haan Monk GrandEvOlution Optic Women Cole White Leather Modern pqwAxEAd7. I had been trying to figure this out for a while without success, and it turns out this suggestion works great: simple implementation, no performance penalty, and no more cascading errors. Thanks internet person!

In addition to showing better error messages, this release is also catching Siren Q2 Vapor Hex E Boot Merrell Hiking Women's Mesh more errors. One big goal of Elm is to have no runtime errors. In practice, this is pretty much already how it goes. You can go months or years without a runtime error. In any case, Elm 0.16 closes one of the last remaining loopholes.

Thanks to Izzy Meckler, the Elm compiler now detects “incomplete pattern matches” which are when a case expression does not handle all possible cases. For example, say we are pattern matching on a list to get the last element:

If someone were to give an empty list to last it just would not know what to do. That scenario is not covered. So this release detects these cases and shows a helpful error message:

This is particularly helpful when you have a large codebase and add a tag to a custom type. Now the compiler will point out all the case expressions scattered throughout your code that need to have an extra branch added to them!

Elm now does tail-call optimizations for self-recursive functions. Lots of fancy words here, but the real meaning is pretty simple. Certain recursive functions can be turned into while loops now. This is a ton faster and does not grow the stack.

Turns out that ES6 will be getting a more advanced version of this feature (details), but it is not clear how long it will be before this starts appearing in popular browsers. In any case, we get some of this now and it happens at compile time.

To get all this working, we ended up improving the whole code generation pipeline. With some relatively minor changes, the number of closures in the generated JavaScript is significantly decreased. This alone led to some quite dramatic performance improvements.

It is kind of cool, but it has three major weaknesses that I did not appreciate at the time.

First, it works against nice indentation in a lot of ways. According to Air NIKE black Grey Top Black Thea Rose Low Sneakers Max 029 Gunsmoke Particle Women’s 5x41xAwF, you should pick 2 or 4 space indent and stick with that for your whole file. The vertical bar in the multi-way if kind of wants 3 space indent. It just looks really bad without it. The style guide also says you should always bring values down a line after = or -> so changing something simple never causes a big stylistic refactor as well. Again, multi-way ifs kind of call to you to not follow this rule because it would lead to 8 space indents or even uglier things.

Second, it is possible to have “incomplete” multi-way ifs. It lets you write silly stuff that can crash:

if | n < 0 -> -1
| n > 0 -> 1

If Vapor Boot Siren Women's E Mesh Hiking Q2 Merrell Hex n is zero there is no branch to take, so this would just crash. Since 0.16 is actually catching all incomplete pattern matches, it felt particularly egregious to allow this kind of thing.

Third, it is totally redundant. You can do the same things with the normal if/then/else syntax. So any multi-way if will turn into something like this:

Note:Mule Estelle The The Comfortview Comfortview Brown 8qwIFxRw Notice that the new version looks a whole lot more like Python or Ruby or JavaScript or C++ or all the other languages. I think many popular languages have a “code texture” that works really well for skimming and recognizing structure. I think having great code texture is mostly a matter of personal style, not the language or paradigm, so we will keep working to discover the most excellent code texture!

Simplified Records

There is kind of a long story here. The short version is that record update uses a normal equals sign now, like this:

{ point | x = 4 }

Instead of using the backwards arrow like before. This was something that a lot of people got tripped up on, even after they had a lot of experience, so overall I think this will make things a bit friendlier. The backwards arrows also led to weird code texture when used within a case such that you have forwards and backwards arrows going everywhere.

Okay, but the long story is interesting if you are into language design!

I added support for this back in 0.7, and at the time, I had never seen a language (with a real working compiler) that allowed field addition and deletion like this. So I had intuition, but no way to get real experience. I worried that it could encourage overly complex code, so from the start I was very conservative, knowing that we could expand or contract the features as we got more data.

Well it has been more than two years since then, and the results are in. Pretty much no one ever used field addition or deletion. In the few cases where people did use it, it got pretty crazy pretty quickly. The one real-world case I know of is recorded here if you want to see, and the code could be rewritten with custom types, which turned out nicer anyway.

Removing addition and deletion will also make Elm easier to optimize (described more here). This is especially true if we are targeting platforms besides JavaScript, but allows some simplifications in JS too. In fact, the benchmarks we ran for 0.16 show that this made record updates a lot faster!

Siren Merrell Boot E Women's Mesh Q2 Hiking Hex Vapor It has been a pretty busy couple months for Elm so there are a lot of folks to thank.

I also want to thank the Elm community. We have been going through some growing pains recently with lots of new folks showing up, and a lot of community members have stepped up to keep things running smoothly. Thank you in particular to Richard, Pete, Joey, Jeff, Max, and Janis. This process has been a bit rough on me, and I do not know how to appropriately thank all the people who have been supportive or just said “I bet I can do this better” and went for it!