过去几天我一直在玩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)
我得到同样的错误。
答案 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)