Haskell 说我的守卫有一个解析错误
Haskell Says My Guard Has A Parse Error
所以过去几天我一直在研究 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)
我遇到了同样的错误。
您应该在 main
之外定义 fib
,而不是在其中。然后你应该从 main
.
中至少删除一个 do
问题是您试图在 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
绑定到您想要的函数。
您还可以在 do
块之外的 main
本地定义 fib
。请记住 do
是使用各种单子绑定函数的语法糖,因此它内部接受的语法与外部接受的语法并不完全相同。而且,事实上,您的 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
操作,你可以将它放在对 [=19 的调用的位置=],像这样:
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)
所以过去几天我一直在研究 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)
我遇到了同样的错误。
您应该在 main
之外定义 fib
,而不是在其中。然后你应该从 main
.
do
问题是您试图在 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
绑定到您想要的函数。
您还可以在 do
块之外的 main
本地定义 fib
。请记住 do
是使用各种单子绑定函数的语法糖,因此它内部接受的语法与外部接受的语法并不完全相同。而且,事实上,您的 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
操作,你可以将它放在对 [=19 的调用的位置=],像这样:
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)