
Christopher L Conway wrote:
I've installed 2.3 and it exhibits the same indentation behavior: any entity appearing on a new line immediately after "module X where" wants to be indented 4 spaces, including function definitions and variable bindings.
Yes, it does do that. And it's correct syntax too. But I tend to override it by putting the first line flush-left. After that, it knows.
"if-then-else" want to be lined up with one another, although both GHC and Hugs reject this layout.
I'll leave that issue for now, it's fiddly. I thought it was fixed in recent GHCs, but it's not something haskell-mode has ever got right.
Here's the result of indent-region on the prior example:
No! No! You can't use indent-region on haskell code. Why not? Because indentation involves *semantic* choices! And how can haskell-mode possibly guess the semantics of your code? indent-region just chooses the 'first choice' in the fairly arbitrary list of choices for each line, I think. You could argue that it could have better heuristics, and guess better more often. Alternatively (and perhaps this makes more sense) you could argue that indent-region should never change the semantics; rather it should just normalise the indentation. I.e. it should be merely a pretty-printer.
module Num where
import IO
main = do putStrLn "Enter a number: " inp <- getLine let n = read inp if n == 0 then putStrLn "Zero" else putStrLn "NotZero"
This is distressing, because I've gotten rather used to letting Emacs worry about indentation for me. (This works well in tuareg-mode for OCaml. But, as I said earlier, I am a layout-sensitive-language newbie.)
You need to get used to hitting <tab> until you see the indentation you want. There are choices to make and emacs can't make them (all) for you. For example, consider the fragment after the 'let'. What you have written is equivalent to this: let n = read inp (if n == 0 then putStrLn "Zero" "NotZero") I.e. you are treating read as a two-argument function, and the second argument is the entire if expression. Haskell layout is really quite simple, when you get used to it. The problem is it's not that easy to explain to someone from an imperative background; because you have to cross two bridges at once - the 'imperative' bridge and the 'layout' bridge. Layout isn't active 'everywhere' in haskell. In fact, arguably, it isn't even active in 'most' haskell. The two contexts in which layout mode applies most often are do expressions and declarations. Declarations is 'mostly' the top level of the file (it also applies if you define more than one name in a let or a where, but that's a relatively advanced technique). Do expressions are introduced by 'do' as you can see. I urge you to experiment more in the REPL (ghci/hugs) and less with loading files, and find lots of examples on the web, and hopefully this will all become clear. Jules