3

I'm learning Haskell through, appropriately enough, the Learn You a Haskell book. Up until the section on guards, none of the code examples have been indented, and I'm wondering how I should properly indent my Haskell code going forward.

The book indents the guard lines in the bmiTell function with four spaces:

bmiTell :: (RealFloat a) => a -> String
bmiTell bmi
    | bmi <= 18.5 = "You're underweight, you emo, you!"
    | bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
    | bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
    | otherwise   = "You're a whale, congratulations!"

Using Haskell Mode's default indentation settings, I can toggle between zero spaces (which gives a compilation error) and two spaces (which seems to work fine) using TAB and S-TAB:

bmiTell :: (RealFloat a) => a -> String
bmiTell bmi
  | bmi <= 18.5 = "You're underweight, you emo, you!"
  | bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
  | bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
  | otherwise = "You're a whale, congratulations!"

The docs make it seem like I shouldn't need to do anything in my Emacs config to get the recommended indentation settings, but after a bit of Googling, I haven't been able to find any code examples with two-space indentation. A search for "Haskell style guide" yields this, which recommends four-space indentation like that used in the book.

Is Haskell Mode's default indentation behavior consistent with the way people commonly format their Haskell code? If not, how should I change my Emacs config to be consistent with the most popular indentation scheme?

Edit: Apparently, I was incorrect about indentation in previous examples. The first use of an if statement is indented like this:

doubleSmallNumber x = if x > 100
                        then x
                        else x*2

But I can't seem to get anything that looks like that using TAB and S-TAB in my current setup.

Sam Estep
  • 12,974
  • 2
  • 37
  • 75
  • 2
    Set it to 4: `(setq haskell-indent-spaces 4)`. – Sibi May 12 '16 at 02:59
  • @Sibi: note that it's available as a [customization variable](https://www.gnu.org/software/emacs/manual/html_node/emacs/Easy-Customization.html) so you can use the customization framework instead of setting it directly via `setq`. – Cactus May 12 '16 at 04:24
  • 2
    I very much prefer two spaces because I tend to run out of horizontal space. I also indent the keyword `where` two spaces and the bindings in its clause another two. – dfeuer May 12 '16 at 05:37
  • @Sibi I tried that and it didn't seem to change anything. – Sam Estep May 12 '16 at 11:43
  • 2
    @Cactus I like to version my `~/.emacs.el` file, and I've found that the "easy customization" in Emacs doesn't play very nicely with source control. – Sam Estep May 12 '16 at 11:46
  • 2
    I daresay the Haskell community is pretty relaxed with regard to indentation consistency. Which is good IMO: this really isn't something that should matter much† if the code is structured in a properly modular fashion. I personally tend to indent `where` only one space, `do` blocks three spaces, and everything else as much as seems to give the best readability for the given circumstances. — †What's important, of course, is that you indent _correctly_ (otherwise Haskell code won't compile anyway), and that you only use spaces, not tabs (about which modern GHC will give a warning). – leftaroundabout May 12 '16 at 14:05
  • @leftaroundabout That makes sense, thanks. I suppose the reason I'm asking is that recently, I've mostly been working in Lisp, where indentation is just about the easiest thing in the world. So you're saying that there would be nothing wrong with me just using the default settings and going with that? – Sam Estep May 12 '16 at 14:16

2 Answers2

0

You can look at some major projects developed in haskell like parsec. In the case of parsec, it seems that they use four spaces for guards.

perplexed
  • 131
  • 5
  • 1
    Thanks, but this doesn't fully answer my question. How should I change my Emacs configuration to be consistent with this indentation scheme? – Sam Estep May 12 '16 at 02:40
0

Here is something I found useful and included in my init.el file (or similar) to force haskell-mode to use four spaces per tab.

(defun haskell-setup ()
    (make-local-variable 'tab-stop-list)
    (setq tab-stop-list (number-sequence 0 120 4))
    (setq indent-line-function 'tab-to-tab-stop)
    (setq haskell-indent-spaces 4))

(add-hook 'haskell-mode-hook 'haskell-setup)