Good Haskell code formatters?

I want to make my code look consistent and neat. I don’t have any personal stylistic preferences at the moment – I want to pick a widely accepted style and stick with it. I’m used to tools like Rust’s rustfmt, which have a well-defined style with good defaults.

What formatters does Haskell have that are similar to them? ormolu and fourmolu look like good options with sensible defaults.

3 Likes

They are. ormolu has sensible default and AFAIK It doesn’t allow for configuration (hence, a single source of “true format”). fourmolu is just a ormolu fork which allow you to customize some attributes like how-many-space-per-tab, let binding should be one-line or splitted, etc…

I prefer fourmolu because I am the kind of guy who wants to waste time configuring meaningless things :laughing: but probably ormolu fits you better from your description

3 Likes

Personally I love using ormolu. The other one you might like to look into is hindent. All the tools have their fans.

And has what some people (including me, but then I mostly chose them) consider more sensible defaults.

6 Likes

We use ormolu at work, and it’s okay enough. I dislike many things about its style, but I like not having to worry about style. If I had my time again, I’d probably look more closely at fourmolu.

2 Likes

Where can I learn about fourmolu's defaults and how they differ from ormolu?

It seems only few, including me, that use stylish-haskell… I find it quite light weight though

3 Likes

Both have very good documentation and live examples in their githubs pages:

2 Likes

We don’t currently have a concise explanation anywhere, but the main ones are: four-space indentation (the original raison d’etre), leading commas, and simpler import/export lists.

4 Likes

I’m also a big fan of stylish-haskell. stylish-haskell does a great job formatting the tedious, entirely systematic parts of the code (mostly import statements), without trying anything tricky with expressions and definitions.

I’ve actually been pretty happy with opinionated formatters in other languages (Rust, Python, etc), but I found that Haskell’s base expression grammar is so minimalist and flexible that automatic formatting routinely gets in the way of writing readable code. Using my own judgement for new lines and alignment in expressions and relying on stylish-haskell for imports and records has been the perfect combination for me. It also helps that Emacs’s default indentation suggestions are pretty solid :slight_smile:

6 Likes

hindent is still around and has some users. I’m trying to keep it working with newer versions of GHC, and got serious help from toku-sa-n

3 Likes

Hello, I’m new to Haskell. Is there an actively maintained formatter that does vertical alignment of =, ::, -> etc? I’m aware of the arguments against vertical alignment, but as a single developer, I prefer this style.

Ormolu and Fourmolu don’t seem to have vertical alignment. I believe stylish-haskell does, but when I tried to install it with cabal install stylish-haskell, the installation failed. My setup is Windows 11 + VSCode + Haskell extension + ghc-9.4.7. Thank you!

2 Likes

How did cabal install fail?

Preprocessing library for stylish-haskell-0.14.5.0..
Building library for stylish-haskell-0.14.5.0..
[ 1 of 26] Compiling Language.Haskell.Stylish.Block ( lib\Language\Haskell\Stylish\Block.hs, dist\build\Language\Haskell\Stylish\Block.o )
[ 2 of 26] Compiling Language.Haskell.Stylish.Config.Internal ( lib\Language\Haskell\Stylish\Config\Internal.hs, dist\build\Language\Haskell\Stylish\Config\Internal.o )
[ 3 of 26] Compiling Language.Haskell.Stylish.Editor ( lib\Language\Haskell\Stylish\Editor.hs, dist\build\Language\Haskell\Stylish\Editor.o )
[ 4 of 26] Compiling Language.Haskell.Stylish.GHC ( lib\Language\Haskell\Stylish\GHC.hs, dist\build\Language\Haskell\Stylish\GHC.o )
[ 5 of 26] Compiling Language.Haskell.Stylish.Comments ( lib\Language\Haskell\Stylish\Comments.hs, dist\build\Language\Haskell\Stylish\Comments.o )
[ 6 of 26] Compiling Language.Haskell.Stylish.Module ( lib\Language\Haskell\Stylish\Module.hs, dist\build\Language\Haskell\Stylish\Module.o )

lib\Language\Haskell\Stylish\Module.hs:54:1: warning: [-Worphans]
    Orphan instance: instance Eq GHC.RawPkgQual
    Suggested fix:
      Move the instance declaration to the module of the class or of the type, or
      wrap the type with a newtype and declare the instance on the new type.
   |
54 | deriving instance Eq GHC.RawPkgQual
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[ 7 of 26] Compiling Language.Haskell.Stylish.Ordering ( lib\Language\Haskell\Stylish\Ordering.hs, dist\build\Language\Haskell\Stylish\Ordering.o )
[ 8 of 26] Compiling Language.Haskell.Stylish.Parse ( lib\Language\Haskell\Stylish\Parse.hs, dist\build\Language\Haskell\Stylish\Parse.o )
[ 9 of 26] Compiling Language.Haskell.Stylish.Printer ( lib\Language\Haskell\Stylish\Printer.hs, dist\build\Language\Haskell\Stylish\Printer.o )
[10 of 26] Compiling Language.Haskell.Stylish.Step ( lib\Language\Haskell\Stylish\Step.hs, dist\build\Language\Haskell\Stylish\Step.o )
[11 of 26] Compiling Language.Haskell.Stylish.Step.Tabs ( lib\Language\Haskell\Stylish\Step\Tabs.hs, dist\build\Language\Haskell\Stylish\Step\Tabs.o )
[12 of 26] Compiling Language.Haskell.Stylish.Step.TrailingWhitespace ( lib\Language\Haskell\Stylish\Step\TrailingWhitespace.hs, dist\build\Language\Haskell\Stylish\Step\TrailingWhitespace.o )
[13 of 26] Compiling Language.Haskell.Stylish.Util ( lib\Language\Haskell\Stylish\Util.hs, dist\build\Language\Haskell\Stylish\Util.o )
[14 of 26] Compiling Language.Haskell.Stylish.Step.Squash ( lib\Language\Haskell\Stylish\Step\Squash.hs, dist\build\Language\Haskell\Stylish\Step\Squash.o )
[15 of 26] Compiling Language.Haskell.Stylish.Step.LanguagePragmas ( lib\Language\Haskell\Stylish\Step\LanguagePragmas.hs, dist\build\Language\Haskell\Stylish\Step\LanguagePragmas.o )
[16 of 26] Compiling Language.Haskell.Stylish.Step.UnicodeSyntax ( lib\Language\Haskell\Stylish\Step\UnicodeSyntax.hs, dist\build\Language\Haskell\Stylish\Step\UnicodeSyntax.o )
[17 of 26] Compiling Language.Haskell.Stylish.Step.Imports ( lib\Language\Haskell\Stylish\Step\Imports.hs, dist\build\Language\Haskell\Stylish\Step\Imports.o )
[18 of 26] Compiling Language.Haskell.Stylish.Step.ModuleHeader ( lib\Language\Haskell\Stylish\Step\ModuleHeader.hs, dist\build\Language\Haskell\Stylish\Step\ModuleHeader.o )
[19 of 26] Compiling Language.Haskell.Stylish.Step.Data ( lib\Language\Haskell\Stylish\Step\Data.hs, dist\build\Language\Haskell\Stylish\Step\Data.o )
[20 of 26] Compiling Language.Haskell.Stylish.Align ( lib\Language\Haskell\Stylish\Align.hs, dist\build\Language\Haskell\Stylish\Align.o )
[21 of 26] Compiling Language.Haskell.Stylish.Step.SimpleAlign ( lib\Language\Haskell\Stylish\Step\SimpleAlign.hs, dist\build\Language\Haskell\Stylish\Step\SimpleAlign.o )
[22 of 26] Compiling Language.Haskell.Stylish.Verbose ( lib\Language\Haskell\Stylish\Verbose.hs, dist\build\Language\Haskell\Stylish\Verbose.o )
[23 of 26] Compiling Language.Haskell.Stylish.Config.Cabal ( lib\Language\Haskell\Stylish\Config\Cabal.hs, dist\build\Language\Haskell\Stylish\Config\Cabal.o )
[24 of 26] Compiling Language.Haskell.Stylish.Config ( lib\Language\Haskell\Stylish\Config.hs, dist\build\Language\Haskell\Stylish\Config.o )
ghc-9.4.7.exe: C:\cabal\store\ghc-9.4.7\hashable-1.4.3.0-1961fe79003fd705645c177b7f4aca0399a4d276\lib\libHShashable-1.4.3.0-1961fe79003fd705645c177b7f4aca0399a4d276.a(#7:LowLevel.o): Not a x86_64 PE+ file.
ghc-9.4.7.exe: Unknown COFF 4 type in getHeaderInfo.

<no location info>: error:
    loadArchive "C:\\cabal\\store\\ghc-9.4.7\\hashable-1.4.3.0-1961fe79003fd705645c177b7f4aca0399a4d276\\lib\\libHShashable-1.4.3.0-1961fe79003fd705645c177b7f4aca0399a4d276.a": failed
[25 of 26] Compiling Paths_stylish_haskell ( dist\build\autogen\Paths_stylish_haskell.hs, dist\build\Paths_stylish_haskell.o )
1 Like

dist/build paths suggest severely outdated Cabal. Could you upgrade to a modern one (or use v2-install)?

1 Like

Ah yes. I did have an old version of cabal. I’ve updated it with choco install cabal. And I was able to successfully run cabal install stylish-haskell. I’m able to format files with stylish-haskell -i myfile.hs.

For some reason, it doesn’t work automatically on save even though I have the stylish-haskell VSCode extension installed, my Haskell extension is set to the stylish-haskell formatter, and C:\cabal\bin is in my PATH. But hopefully, I’ll figure that out soon. Thanks for your help!

1 Like
  • I want to limit my columns to e.g. 100 chars. It’s cool to see fourmoulu has this! (I’ve been using Ormolu and limiting columns for Haskell code manually so far. This will save me a lot of time!)
  • But what about comments? Currently I use the “rewrap” vscode extension to limit column length for comments, but it doesn’t work in certain cases within Haskell code.
  • Are there any Haskell code formatters out there that also deal with comments? (With support for bulleted/numbered lists etc. like “rewrap”)

Fourmolu doesn’t currently have any support for wrapping comments, but I’m sure we’d merge a PR implementing it as an option. Please consider at least opening a GitHub issue to track this.

I’m pretty sure none of the other formatters have this feature either.

1 Like