Emacs/Indentation

From HaskellWiki
< Emacs
Revision as of 10:19, 18 May 2012 by Chrisdone (talk | contribs) (First commit.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Emacs can indent Haskell in various ways. The most common is the tab cycle.

Indentation using tab cycle

Haskell-mode offers intelligent indentation. As Haskell source code uses indentation aware code blocks, there is usually more than one column for which indentation makes sense.

Hit tab a few times to see a few different indentation possibilities.

For example, imagine the following is open in a haskell-mode buffer, where ! represents the point:

foo :: Int -> String
foo 0 = f 4 ++ s
  where f 4 = "hello" ++ 
!

If you ask haskell-mode to indent for you, where should it indent to? There are four basic options:

  1. You want to finish off the expression you were writing in the last line. Haskell-mode indents to be underneath the " character at the beginning of "hello":
    where f 4 = "hello" ++
                !
    

    This is debatably a bad choice as you'd probably want to indent a bit further in to make it clear that you were carrying on an expression, but the layout rule would accept something like the following:

    where f 4 = "hello" ++
                "world"
    
  2. You want to add a second equation for f. Haskell-mode will indent to line up with the first argument, and fill in the f in the equation:
    where f 4 = "hello" ++
          f !
    

    This is an unlikely choice as the expression in the previous line isn't complete, but haskell-mode isn't smart enough to know that. (If f had been something without arguments, like where f = "hello", then it's impossible to have more than one equation and haskell-mode won't offer this indentation level.)

  3. You want to add a second binding to the where-block. Haskell-mode indents to line up with the f:
    where f 4 = "hello" ++
          !
    
  4. You want to start an entirely new top-level binding. Haskell-mode indents to the first column:
    foo :: Int -> String
    foo 0 = f 4 ++ s
      where f 4 = "hello" ++
    !
    

These four locations can be reached by repeatedly pressing TAB. This is what's known as the tab-cycle. The innermost location is offered first, then cycling progresses outwards. Although this may seem like an inefficient system (and it is indeed a shame that Haskell's design didn't result in an unambiguous indentation system), you do quickly get used to the tab-cycle and indenting Haskell code.

Notes:

Do not use indent-region

Using indent-region is generally a bad idea on Haskell code, because it would need to know which of the tab-cycle stops you wish to choose for each line. The innermost one is chosen in each case, which often results in unusable code. Moral: just don't use indent-region with haskell-mode.