Tools to indent badly indented code

haskell, indentation

Solution

This is next to impossible to do (and I'm writing this as a response because I've been looking for a tool myself that can do this) because unindented Haskell code can be very ambiguous.

Consider the code:

describeList :: [a] -> String
describeList xs = "The list is " ++ what xs
  where what [] = "empty."
        what [x] = "a singleton list."
        what xs = "a longer list."

Let's also consider some alternative, also valid, interpretations:

 -- top-level function "what" without type signature
describeList :: [a] -> String
describeList xs = "The list is " ++ what xs
  where what [] = "empty."
what [x] = "a singleton list."
what xs = "a longer list."

-- same as above
describeList :: [a] -> String
describeList xs = "The list is " ++ what xs
  where what [] = "empty."
        what [x] = "a singleton list."
what xs = "a longer list."

-- There might be a `data String a b`, so `String describeList xs` is
-- a type. The clause then becomes a guarded pattern match (similar to 
-- `let bar :: Int = read "1"`) with scoped type variables. The `where`
-- clause is still syntactically valid. The whole thing might not compile,
-- but a syntax tool can't know that.
describeList :: [a] -> String
                       describeList xs = "The list is " ++ what xs
  where what [] = "empty."
        what [x] = "a singleton list."
what xs = "a longer list."

Problem

Consider the following piece of operational Haskell code : Code A ``` describeList :: [a] -> String describeList xs = "The list is " ++ what xs where what [] = "empty." what [x] = "a singleton list." what xs = "a longer list." ``` which is a snippet taken from Syntax in Functions. Now suppose that we start off with the following piece of badly indented and non-operational Haskell code : Code B ``` describeList :: [a] -> String describeList xs = "The list is " ++ what xs where what [] = "empty." what [x] = "a singleton list." what xs = "a longer list." ``` Then is there any tool which can take the badly indented code (Code B) and correctly indents it so as to yield operational code (Code A)?

Original source