简体   繁体   English

Haskell 使用 foldr 实现 rpn

[英]Haskell implementation of rpn using foldr

I am trying to write a reverse Polish notation evaluator using foldr and this is what I have so far :我正在尝试使用 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 [] 

I have tried to resolve the error by swapping the positions of this : (x * y):ys and this (x:y:ys) but I keep getting this error:我试图通过交换 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.

any help would be appreciated on how to resolve this.任何有关如何解决此问题的帮助将不胜感激。 Thank you谢谢

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

Try saying试着说

step (x:y:ys) "*" = (x * y) : ys

The same for the other operators.其他运营商也一样。 The last line of step looks OK. step的最后一行看起来没问题。

There are some problems here.这里有一些问题。 The first one is that you swap "input" and "output" in your step function.第一个是您在step函数中交换“输入”和“输出”。 Indeed if you encounter a multiplication ( "*" ) you pop two items from the stack, and push the result of the multiplication on the stack.实际上,如果您遇到乘法 ( "*" ),您会从堆栈中弹出两个项目,并将乘法的结果压入堆栈。 The step function should thus look like:因此, 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

The parenthesis for the (x:y:ys) are necessary here, since we use the same parameter: a list of Int s. (x:y:ys)的括号在这里是必要的,因为我们使用相同的参数:一个Int列表。

Furtermore you can not write foldr step [] and expect that it will yield an Int .此外,您不能编写foldr step []并期望它会产生一个Int The foldr will return the accumulator, and that is a list of Int s, hence foldr step [] somelist :: [Int] . foldr将返回累加器,这是一个Int列表,因此foldr step [] somelist :: [Int] You can use for example head to obtain the first element.例如,您可以使用head来获取第一个元素。

The type of the accumulator and the element should be swapped, we can make use of flip :: (a -> b -> c) -> b -> a -> c to flip the two parameters.累加器和元素的类型应该交换,我们可以使用flip :: (a -> b -> c) -> b -> a -> c来翻转两个参数。

Finally you should reverse the list of strings, not the output, thus the function should look like:最后,您应该反转字符串列表,而不是输出,因此该函数应如下所示:

rpnRec :: [String] -> Int
rpnRec = safeHead . foldr (flip step) [] . reverse
    where safeHead [] = 1
          safeHead (x:_) = x

For example:例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM