[英]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.