哈斯克尔说我的警卫有一个解析错误

时间:2016-05-04 20:11:05

标签: haskell whitespace guard pattern-guards

过去几天我一直在玩Haskell,我决定对斐波那契序列做一个基本的定义。所以我写了这段代码:

main = do
    fib :: (Integral a) => Int -> Int
    fib x
        | x == 0 = 0
        | x == 1 = 1
        | x >= 2 = fib (x - 2) + fib (x - 1)
    do { print (fib 5) }

我收到一条错误消息:

4:17: parse error on input `|'

我怀疑标签错误,所以我尝试了我能找到的每个空白修复,但我无法找到错误的内容!

编辑:所以我做了人们的建议,我现在有了这个代码:

fib :: (Integral a) => Int -> Int
main = do
    fib x
        | x == 0 = 0
        | x == 1 = 1
        | x >= 2 = fib (x - 2) + fib (x - 1)
    print (fib 5)

我得到同样的错误。

3 个答案:

答案 0 :(得分:3)

您应该在fib之外定义main,而不是在do内。然后,您应该从main中删除至少一个{{1}}。

答案 1 :(得分:3)

问题是你试图在do块中定义函数而不实际使用任何构造来定义事物(如let)。

尝试在块外定义函数:

fib :: (Integral a) => Int -> Int
fib x | x == 0 = 0
      | x == 1 = 1
      | x >= 2 = fib (x - 2) + fib (x - 1)

main = print (fib 5)

如果你坚持在本地定义函数(在由do块的语句形成的表达式中):

main = do
    let
        fib :: (Integral a) => Int -> Int
        fib x | x == 0 = 0
              | x == 1 = 1
              | x >= 2 = fib (x - 2) + fib (x - 1)
    print (fib 5)

注意如何使用let将新变量fib绑定到您想要的函数。

答案 2 :(得分:1)

您还可以在fib块之外的main本地定义do。请记住,do是使用各种monadic绑定函数的语法糖,因此其中接受的语法与在其外部接受的语法不完全相同。而且,事实上,您的main甚至不需要do阻止,因为您只需拨打print而不是将任何IO行动链接在一起。

main = let
         fib x | x == 0 = 0
               | x == 1 = 1
               | x >= 2 = fib (x - 2) + fib (x + 1)
       in
         print (fib 5)

或者您可以使用where

main = print (fib 5)
       where
         fib x | x == 0 = 0
               | x == 1 = 1
               | x >= 2 = fib (x - 2) + fib (x + 1)

它们是相同的,问题就在于本地绑定的实际位置。 let .. in为您提供了一个新块,其中新绑定在范围内,而where使其绑定在其附加的函数范围内可用。

如果看起来很可能,您确实需要一个do块,以便您可以执行多个IO操作,那么您可以将其替换为print的调用。 ,像这样:

main = let
         fib x | x == 0 = 0
               | x == 1 = 1
               | x >= 2 = fib (x - 2) + fib (x + 1)
       in
         do print (fib 5)
            print (fib 6)