列表 monad 的“do”符号中的解析错误

Parse error in list monad's `do` notation

好的,这是一个奇怪的。

这非常有效:

test = do
  x <- [1..5]
  y <- [1..5]
  [x+y, x-y]

但是这个:

test = do
  x <- [1..5]
  y <- [1..5]
  [
    x+y,
    x-y
  ]

惨败。 GHC 完全 拒绝 解析它。无论我如何摆弄它,我似乎都无法说服 GHC 允许我将列表分散到多行。这是一个问题,因为如果你用 表达式替换 x+yx-y,它很快就会变得难以阅读......

有谁知道为什么这不起作用,我怎样才能强制它起作用? (或者至少做一些看起来清晰的事情?)

如果我解析它,我会收到以下错误:

File.hs:10:3: error:
    parse error (possibly incorrect indentation or mismatched brackets)

我认为解析器只是将右方括号 ] 视为新语句。并且它抱怨之前的声明没有右括号(而新的是没有左括号的右括号)。如果你将它向右推一列,它会正确解析(至少对于 GHC-8.0.2)

test = do
  x <- [1..5]
  y <- [1..5]
  [
    x+y,
    x-y
   ] -- one space to the right

只要您不返回到之前的缩进级别(此处向左 space),就应该没问题。因为编译器会将其视为一个 do 语句。

do 之后,与 do 之后的第一个单词在同一列开始的每一行都开始一个新条目。使用显式大括号,您的代码相当于

test = do
  { x <- [1..5]
  ; y <- [1..5]
  ; [
      x+y,
      x-y
  ; ]
  }

这是由于 。正如我们所看到的,最后一个分号不应该出现——为了避免它,我们应该将最后一行缩进更多。

这里有几种合法的写法:

test = do
  [x,y] <- replicateM 2 [1..5]
  [
    x+y
   ,x-y
   ]

test = do
  [x,y] <- replicateM 2 [1..5]
  [ x+y
   ,x-y ]

test = do
  [x,y] <- replicateM 2 [1..5]
  [ x+y ,
    x-y ]

test = do
  [x,y] <- replicateM 2 [1..5]
  id [ x+y
     , x-y ]

test = do
  [x,y] <- replicateM 2 [1..5]
  id [
       x+y,
       x-y
     ]

test = do
  [x,y] <- replicateM 2 [1..5]
  ([
     x+y,
     x-y
   ])