Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Haskell not accept this syntax for lists?

Tags:

haskell

Consider the following code snippet in Idris:

myList : List Int
myList = [
  1,
  2,
  3
]

The closing delimiter ] is on the same column as the declaration itself. I find this a quite natural way to want to format long, multi-line lists.

However, the equivalent snippet in Haskell fails to compile with a syntax error:

myList :: [Int]
myList = [
  1,
  2,
  3
]

>>  main.hs:9:1: error:
>>     parse error (possibly incorrect indentation or mismatched brackets)?
>>   |
>> 9 | ]
>>   | ^

And requires instead the the closing delimiter ] is placed on a column number strictly greater than where the expression is declared. Or at least, as far as I can garner, this seems to be what is going on.

Is there a reason Haskell doesn't like this syntax? I know there are some subtle interactions between the Haskell parser and lexer to enable Haskell's implementation of the offsides rule, so perhaps it has something to do with that.

like image 446
Nathan BeDell Avatar asked Aug 15 '26 21:08

Nathan BeDell


1 Answers

Well, ultimately the answer is just “because the Haskell language standard demands it to be parsed this way”.

As to for some reasoning why this is a good idea, it's that indentation is the primary way code is structured, and parentheses/brackets only come in locally. I find this much more consequent than Python's attitude that indentation is kind of the primary structure, but for an expression to spread over multiple lines you actually need to wrap it in parentheses. (Not saying that these are the only two ways it could be done.)

Note that if you really want, you can always disable the indentation sensitivity completely, with something like

myList :: [Int]
myList = l where {
l = [
   1,
   2,
   3
]}

But I would not recommend it. The preferred style to write multiline lists is

myList
 = [ 1
   , 2
   , 3
   ]

or

myList = [ 1
         , 2
         , 3 ]

Again, I would argue that this leading-comma style is much preferrable to the trailing-comma one most programmers in other languages use, especially for nested lists: the commas become “bullet points” aligned with the opening bracket, which makes the AST structure very clear.

myMonstrosity :: [(Int, [([Int], Int)])]
 = [ ( 1
     , [ ( [37,43]
         , 9 )
       , ( [768,4,9807,3,4,98]
         , 15 ) ]
     )
   , ( 2, [] )
   , ( 3
     , [ ( [], 300 )
       , ( [0..4000], -5 ) ]
     )
   ]
like image 127
leftaroundabout Avatar answered Aug 18 '26 19:08

leftaroundabout



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!