列表monad的“do”表示法中的解析错误

时间:2017-07-08 08:30:17

标签: list haskell syntax monads 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允许我将列表分散到多行。这是一个问题,因为如果您使用 big 表达式替换x+yx-y,很快就会难以阅读...

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

3 个答案:

答案 0 :(得分:4)

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

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

这是由于indentation rules。我们可以看到,最后一个分号不应该存在 - 为了避免它,我们应该更多地缩进最后一行。

答案 1 :(得分:2)

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

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

只要你不回到之前的缩进级别(这里左边是一个空格),它应该没问题。由于编译器会将其视为一个do - 语句。

答案 2 :(得分:2)

以下是一些合法写法的方法:

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
   ])