输入解析错误 'if'

Parse error on input 'if'

我似乎无法弄清楚为什么这段代码不起作用:

sgetLine  =  do  x <- getChar
              if x == '\n' 
                 then do 
                  putChar x
                  return []
                 else do 
                  putChar '_'
                  xs <- sgetLine
                  return (x:xs) 

奇怪的是,当我这样做时代码有效

sgetLine  =  do { x <- getChar
            ; if  x == '\n' 
                then do 
                 putChar x
                 return []
                else do 
                 putChar '_'
                 xs <- sgetLine
                 return (x:xs)}

感谢您的帮助!

因为空格在 Haskell 中很重要。您需要遵循缩进规则或使用显式大括号和分号(如在第二个代码块中)。这里有两种方法(还有其他方法)来修复第一个块:

sgetLine  =  do  x <- getChar
                 if x == '\n' 
                   then do 
                     putChar x
                     return []
                   else do 
                     putChar '_'
                     xs <- sgetLine
                     return (x:xs)

-- I prefer this one. In any case, it's just a matter of style, so YMMV.
sgetLine  =  do  
  x <- getChar
  if x == '\n' 
    then do 
      putChar x
      return []
    else do 
      putChar '_'
      xs <- sgetLine
      return (x:xs)

do 块中的行必须缩进相同的量,并且缩进到 do 行的右侧。这样,编译器就可以找出您的 do 块的开始和结束位置,而无需您编写显式大括号。

另请参阅:Haskell “where” indentation: why must it be indented past identifier?问题是关于 where 而不是 do,但一般原则是相同的,那里的答案很好地涵盖了它。

我怀疑您设置了五个 space 制表位,这使得 x <- getCharif x == '\n' 行在您的屏幕上排成一行。但是,编译器使用八个 space 制表位,因此 if x == '\n' 行在编译器看来缩进了很多。

您应该使用 spaces 进行对齐,为缩进保留制表符。 (很多人会建议只使用 spaces,but I won't。)