How does elm-format work for the Elm community?

The Swift community is currently considering having an official style guide and formatter for Swift. This is obviously a heated topic, so I thought we could ask how having some kind of official style guide and mostly non-configurable elm-format worked for the Elm community. How do you feel about elm-format?

  • I don’t use it
  • It took me a while to accept it
  • Beats having to discuss formatting issues all the time
  • I love it

0 voters

Any other feedback in comments is also welcome. Thank you!

We asked a similar question in the State of Elm survey last year.

Quickly: the vast majority of respondents said that they prefer to use elm-format.


Loving it, except for the (..) expansion :slight_smile: Doesn’t improve over time, still gets me almost daily.


To clarify, elm-format is 100% non-configurable.

Personally I consider that one of its best features! There is nothing to argue about with teammates.


Being 100% non-configurable is the way to go if possible – that’s my advice at least. Here are some things I’ve learned from the Prettier project:

  • Adding one option makes it hard to say no to further options.
  • Changing something because X people want it usually means X other people asking to change it back.
  • Do your research and pick the most common style for everything. Don’t release too early.

To clarify further:
Elm-format’s output depends on the current line breaks in the source. It’ll try to keep stuff in one line, if thats how it was before.

For example: if you wrote a list literal in one line, its formatted in one line in the output. If you add a newline anywhere in the list literal, it’ll split all elements into its own line.

This is one oft the things I really love about elm-format!


This is actually one of the things I dislike about elm-fomat!

Can you please clarify that a bit more? I just feel it fits the “nothing wrong about being explicit”-mindset

I don’t like the phrase “nothing wrong about being explicit”, because it’s not an explanation, but rather a rule of thumb, on one hand, on another – Elm is far from following it. Imagine adding type signature to every variable that you introduce, for example.

In my experience, listing exported symbols doesn’t really help with reading the code very often (unlike explicit list of what’s imported, or qualified imports), doesn’t always match “public interface”, esp when you want to test things, and often people do want to use internal stuff only because you didn’t cover some scenarios via public api.

I like Haskell’s and Python’s approaches much better, one giving additional .Internal module for non-public stuff (still being exposed for tests and brave users), another prefixing private symbols with _.

That being said, I think having elm-format not being configurable is a wonderful feature, and I would rather keep it so, even if it’ll do the (..)-expansion. I’ll probably just hack my Emacs to add the export for me without going to the top all the time.

1 Like

One of the biggest troubles a large code base can run into is improper module interface design. I’ve been there and it is not pretty.

If you want to test things and feel you need more than the public API of the module, you might have an issue in your API. The implementation details should never leak into your testing. The module should remain a black box.

I would be comfortable even with making (..) illegal for exports.

If you want to learn more about this way of looking at modules, I highly recommend Barbara Liskov’s - The Power of Abstraction talk.

Again, these are mostly rules of thumb and bad explanations that are easy to vary, or aren’t even defined. Additionally, two solutions from other languages mentioned don’t restrict you from having both things in place, without the burden to list your exports.

I’ll put the talk you’ve mention to my “listening list”, thank you. From my side, I recommend reading “The Beginning of Infinity” by David Deutsch to better understand what constitutes good explanations, nature of abstraction, and many other useful things.

You can still use the Haskell pattern if you really want to test the implementation.

1 Like

After giving it some more thought, I think I know what would be my best argument for elm-format to not expand the (..) for me. It would contradict Elm’s advice called Do Not Plan Ahead. Elm is sufficiently more suitable for late refactoring and decision making, and initially exposing all symbols would perfectly fit into that ideology, in my opinion.

1 Like

I am 7 weeks into a semester of teaching mostly new programmers with Elm. The module is on Data Visualization so uses Elm as a means to an end, rather than teaching programming per se.

Elm format (built into our Atom/prettier environment by default) has made my job so much easier as I don’t even have to mention formatting rules and can focus on the important stuff. Formatting can often trip up new programmers who have no experience of the difference between layout requirements, layout conventions and layout idiosyncrasies, so it’s great not having to use up valuable teaching/learning time discussing this.

Like some others, I don’t agree with every layout rule built into elm-format (e.g. whitespace around one-line comments). but the benefit of having a non-negotiable set of formats vastly outweighs any disbenefits.


When working on a package, I love the (…) expansion! When working on an application. Especially starting a new application, it’s really slows me down.

Maybe there could be a compromise where if you’re working on a package, it’ll do it automatically. But if you’re working on an application, it won’t expand for you unless you use some CLI flag or something. It’s better since 0.19 compiles so fast, but I really miss being able to use elm format to check my syntax. I just don’t use elm-format as much while coding anymore since it forces me to constantly replace the export list with (…) because I’m still discovering how I want my code to be structured.

1 Like

There is one case where the elm-format expansion of (..) can lead to bugs, which is where it happens in a module with multiple elm-test test suites:

  • write exposing (..) in a test module with suite1
  • elm-format replaces it with exposing (suite1)
  • add suite2 but forget to add it to the exposing list
  • this means that suite2 doesn’t get executed when running tests
  • et voila, possibly bugs go undetected, as it isn’t obvious that suite2 is skipped.

I agree with @jackhp95 about elm-format handling of (..), sometimes I love it, sometimes it’s frustrating, depending on what I work on.

The main issue I think is that it is not about formatting anymore as it changes the meaning of the code.
Where to put the limit?

A good rule in my opinion could be that the compiler generated AST (before and after elm-format) should never be modified except ordering. I have not thought enough about it though to know if this would prevent other features.

As an aside, I love how it orders the exposed symbols identically to the documentation structure for a package, this is really nice. For example Element.Border.


I personally love it when elm-format removes unnecessary parenthesis. It has helped me understand precedence a lot better between operators and function calls.


I doubt that this changes the compiler AST. Parentheses are usually not part of the AST that knows how to group things from its structure.

Note: I clarified in my previous post that I was talking about the compiler AST, not the elm-format one that may want to keep more information about the original formatting (like single-line or multi-lines for some expressions).


This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.