Haskell中solveRPN函数出现类型错误的原因是什么?
RPN求解代码的类型错误分析与修复
首先看你提供的原始代码:
solveRPN :: String -> Double solveRPN rpnString = head foldl . foldingFunction [] . words where foldingFunction (x:y:ys) "*" = (x * y):ys foldingFunction (x:y:ys) "+" = (x + y):ys foldingFunction (x:y:ys) "-" = (x - y):ys foldingFunction xs numberString = read numberString:xs
你遇到的错误信息是:
_01.hs:874:50: error: • Couldn't match type ‘Char’ with ‘[Char]’ Expected type: String Actual type: Char • In the first argument of ‘read’, namely ‘numberString’ In the first argument of ‘(:)’, namely ‘read numberString’ In the expression: read numberString : xs | 874 | foldingFunction xs numberString = read numberString:xs | ^^^^^^^^^^^^ Failed, 1 module loaded.
错误原因拆解
这个类型错误的核心是函数应用的优先级和组合顺序完全写错了:
Haskell里函数应用的优先级远高于.(函数组合运算符),所以你写的head foldl . foldingFunction [] . words会被Haskell解析成:
(head foldl) . (foldingFunction []) . words
这完全不符合你的意图——你本来想的是把words rpnString传给foldl foldingFunction [],然后取结果的head,但现在的写法里,head foldl试图从foldl这个函数本身(而不是foldl的返回值)取头部,这在类型上是完全不合法的,直接打乱了整个代码的类型推导逻辑。
因为类型推导混乱,Haskell错误地把foldingFunction的第二个参数numberString推断成了Char类型(而不是words返回的String类型),而read需要的是String(也就是[Char]),所以才会出现“无法匹配Char和[Char]”的错误。
修复后的代码
我们需要调整函数应用的顺序,用$(函数应用运算符,优先级最低)来明确执行顺序,同时顺便修正RPN运算的顺序问题(比如减法的操作数顺序):
solveRPN :: String -> Double solveRPN rpnString = head $ foldl foldingFunction [] $ words rpnString where foldingFunction (x:y:ys) "*" = (y * x) : ys foldingFunction (x:y:ys) "+" = (y + x) : ys foldingFunction (x:y:ys) "-" = (y - x) : ys foldingFunction xs numberString = read numberString : xs
关键修复点
- 修正函数执行顺序:用
$让foldl foldingFunction []先处理words rpnString的结果,再用head取最终列表的头部,这样类型推导就能正常工作,numberString会被正确推断为String类型,read也就不会报错了。 - 调整运算操作数顺序:RPN的规则是后出现的操作数先参与运算,比如输入
"3 4 -"应该计算4 - 3而不是3 - 4,所以我们需要把弹出的两个数顺序反过来(y是先入栈的数,x是后入栈的),这样结果才符合RPN的预期。
内容的提问来源于stack exchange,提问作者Madderote
相关产品推荐
相关产品推荐

