Haskell代码报parse input error错误的原因排查咨询
Haskell语法错误排查:parse error on input 'addfunc'
问题说明
我编写了一个Haskell程序,功能是:输入英文单词形式的数字(如"one""two"等),输入"sum"时输出当前总和并继续运行,输入"end"时输出最终总和并退出程序。但代码出现了解析错误,报错位置在addfunc l;行,错误信息为:
error: parse error on input 'addfunc' 17. addfunc l;
尝试调整空格数量或移除该行上方的分号后,错误依然存在,想知道是不是缩进问题导致的。
原代码
main = addfunc 0 addfunc :: Int -> IO () addfunc l = do { input <- getLine; let n = myStrToI input ; if n == -2 then do { putStrLn("The final sum is: " ++ show (l)); return (); } else if n == -1 then putStrLn("The current sum is: " ++ show(l)); addfunc l; <--Error Here else addfunc (n+l) } myStrToI :: [Char] -> Int myStrToI l | l == "zero" = 0 | l == "one" = 1 | l == "two" = 2 | l == "three" = 3 | l == "four" = 4 | l == "five" = 5 | l == "six" = 6 | l == "seven" = 7 | l == "eight" = 8 | l == "nine" = 9 | l == "sum" = -1 | l == "end" = -2
错误原因与修复方案
这个错误确实和do块的语法规则有关——你混合使用了大括号+分号、缩进两种do块写法,同时在else if n == -1 then分支下没有用do包裹多个IO动作,导致编译器无法正确解析。
Haskell的if-then-else要求then和else后面的表达式类型必须一致,这里都是IO ()类型。如果一个分支里有多个IO动作(比如先打印再递归调用),必须用do把这些动作组合成一个IO ()表达式。
另外,Haskell社区更推荐用缩进风格写do块,避免大括号和分号带来的语法混乱。下面是修复后的代码:
main = addfunc 0 addfunc :: Int -> IO () addfunc l = do input <- getLine let n = myStrToI input if n == -2 then do putStrLn $ "The final sum is: " ++ show l return () else if n == -1 then do putStrLn $ "The current sum is: " ++ show l addfunc l else addfunc (n + l) myStrToI :: String -> Int myStrToI l | l == "zero" = 0 | l == "one" = 1 | l == "two" = 2 | l == "three" = 3 | l == "four" = 4 | l == "five" = 5 | l == "six" = 6 | l == "seven" = 7 | l == "eight" = 8 | l == "nine" = 9 | l == "sum" = -1 | l == "end" = -2 | otherwise = 0 -- 可选:处理无效输入,避免运行时崩溃
主要修复点:
- 移除了所有不必要的大括号和分号,采用缩进风格组织
do块代码,确保每个do块内的语句缩进一致。 - 在
else if n == -1 then分支后添加了do关键字,把putStrLn和addfunc l两个IO动作组合成一个合法的IO ()表达式。 - 将
[Char]替换为更易读的String(两者是同义词),并用$运算符简化了putStrLn的写法,减少冗余括号。 - 可选添加了
| otherwise = 0分支,处理未匹配的输入(比如乱输的单词),避免程序运行时崩溃。
内容的提问来源于stack exchange,提问作者Poseidon9850
相关产品推荐
相关产品推荐

