Haskell 使用 foldr 实现 rpn

标签 haskell

我正在尝试使用 foldr 编写一个反向波兰符号评估器,这是我目前所拥有的:

step :: [Int] -> String -> [Int] 
step (x * y):ys "*" = (x:y:ys)
step (x + y):ys "+" = (x:y:ys)
step (y - x):ys "-" = (x:y:ys)
step xs numberString = read numberString:xs

rpnRec ::[String] -> Int   
rpnRec [] = 1                                          
rpnRec = reverse .foldr step [] 

我试图通过交换 this 的位置来解决错误:(x * y):ys 和 this (x:y:ys)
但我不断收到此错误:
Rpn.hs:14:7: error: Parse error in pattern: x * y
   |
14 | step (x * y):ys "*" = (x:y:ys)
   |       ^^^^^
Failed, no modules loaded.

任何有关如何解决此问题的帮助将不胜感激。谢谢

最佳答案

这里有一些问题。第一个是您在 step 中交换“输入”和“输出”。功能。实际上,如果您遇到乘法( "*" ),您将从堆栈中弹出两个项目,并将乘法的结果压入堆栈。 step因此,函数应如下所示:

step :: [Int] -> String -> [Int] 
step (x:y:ys) "*" = x*y:ys
step (x:y:ys) "+" = x+y:ys
step (x:y:ys) "-" = x-y:ys
step xs numberString = read numberString:xs
(x:y:ys) 的括号这里是必要的,因为我们使用相同的参数:Int 的列表s。

此外你不能写foldr step []并期望它会产生 Int . foldr将返回累加器,即 Int 的列表s,因此 foldr step [] somelist :: [Int] .您可以使用例如 head获取第一个元素。

累加器和元素的类型应该交换,我们可以使用 flip :: (a -> b -> c) -> b -> a -> c 翻转两个参数。

最后,您应该反转字符串列表,而不是输出,因此该函数应如下所示:
rpnRec :: [String] -> Int
rpnRec = safeHead . foldr (flip step) [] . reverse
    where safeHead [] = 1
          safeHead (x:_) = x

例如:
Prelude> rpnRec ["2", "3", "*", "5", "+"]
11

关于Haskell 使用 foldr 实现 rpn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59593356/

相关文章:

haskell - 构建 DAG 以便重用节点

haskell - 秒差距组合器和文本/字节串

haskell - ghc-pkg 和 cabal 是什么关系?

haskell - 是否可以组合类型类的实例?

haskell - Coyoneda和自由仿函数有什么区别

list - Haskell 中的列表元素相乘

Haskell 懒惰 - 我如何强制 IO 更快发生?

haskell - 为什么app在Applicative里面可用?

haskell - 通过具有不同数量参数的方程式定义函数

haskell - 如何使用 System.Cron.Schedule 处理长时间运行的作业?